Skip to content

MySQL 知识卡片(简历版)

这份卡片按你当前简历的项目强度整理。

目标不是 DBA 级全覆盖,而是:

  • 能撑住 黑马点评 的数据库一致性与高并发追问
  • 能撑住 苍穹外卖 AI 智能客服 Agent 里的条件更新、唯一约束、事务边界追问
  • 能过常规后端一面 / 二面的 MySQL 主干题

1. 存储引擎

  • 线上主流默认答 InnoDB
  • InnoDB:支持事务、行锁、MVCC、外键、崩溃恢复
  • MyISAM:不支持事务、不支持行锁、不支持崩溃恢复
  • 为什么线上基本选 InnoDB
  • 要事务
  • 要并发
  • 要 crash-safe
  • 要 MVCC

2. 索引

  • 索引快的核心不是“排序”,而是 B+ 树降低磁盘 IO
  • B+ 树更适合数据库的原因
  • 非叶子节点只存 key,树更矮
  • 查询路径更稳定
  • 叶子节点链表化,范围查询更友好
  • 红黑树不行:树太高,磁盘 IO 多
  • 哈希表不行:不支持范围查询
  • 主键索引 = 聚簇索引,叶子节点存整行数据
  • 二级索引 = 辅助索引,叶子节点存主键值
  • 回表:二级索引查到主键后,再回主键索引查整行
  • 覆盖索引:查询字段都在索引里,省掉回表

3. 联合索引

  • 联合索引 (a,b,c) 本质是按 (a,b,c) 这个复合键排序
  • 排序规则:
  • 先按 a
  • a 相同再按 b
  • a,b 都相同再按 c
  • 最左前缀本质:
  • a 全局有序
  • b 只有在 a 确定后局部有序
  • c 只有在 a,b 都确定后局部有序
  • where a=1 and c=1
  • 先用 a
  • c 再过滤
  • where b=1 and c=1
  • 一般用不好这个联合索引
  • where a=1 and b>2 and c=3
  • a 能用
  • b 能用到范围起点
  • 到了范围查询,c 很难继续完整利用索引排序能力

4. 索引失效

  • 联合索引没走最左匹配
  • 索引列上做函数 / 计算
  • 隐式类型转换
  • like '%xx'
  • or 一边没索引
  • 命中数据量太大
  • 优化器认为大量回表的随机 IO 成本高于全表扫描顺序 IO
  • 记一句:
  • 失效不只是不符合规则
  • 也可能是优化器算完成本后主动放弃索引

5. EXPLAIN

  • type 看访问方式
  • 至少要知道:system > const > eq_ref > ref > range > index > ALL
  • 一般看到 ALL 要警惕全表扫描
  • key 看实际用了哪个索引
  • rows 看预计扫描多少行
  • extra 常看:
  • Using index:覆盖索引
  • Using where:还要额外过滤
  • Using filesort:额外排序
  • Using temporary:临时表,通常不理想

6. 事务隔离级别

  • 四种隔离级别:
  • 读未提交
  • 读已提交
  • 可重复读
  • 可串行化
  • 读未提交:脏读、不可重复读、幻读都可能发生
  • 读已提交:防脏读
  • 可重复读:防脏读、防不可重复读
  • 可串行化:隔离最强,并发最差
  • InnoDB 默认是 RR

7. MVCC

  • MVCC 主要解决的是 快照读可见性
  • 核心依赖:
  • undo log
  • 隐藏字段
  • Read View
  • RC
  • 每次快照读生成新的 Read View
  • 防脏读,但可能不可重复读
  • RR
  • 第一次快照读生成 Read View
  • 后续复用
  • 所以快照读下可重复读
  • 记一句:
  • MVCC 管可见性

8. 锁

  • 当前读 才更容易扯到锁
  • 常见当前读:
  • select ... for update
  • update
  • delete
  • 行锁:锁具体记录
  • 间隙锁:锁区间,重点是 防插入
  • 临键锁:记录锁 + 间隙锁
  • 意向锁:表级标记锁,方便锁兼容判断
  • 记一句:
  • MVCC 管快照读
  • 锁机制管当前读并发控制

9. 幻读边界

  • 幻读不能简单全归因于 MVCC 解决
  • 快照读场景下,RR 下很多时候“看起来没有幻读”
  • 本质是一直在看同一张快照
  • 真正要防范围内插入新记录
  • 主要靠间隙锁 / 临键锁

10. 三大日志

  • redo log:物理日志,负责持久性和崩溃恢复
  • undo log:负责回滚和 MVCC
  • binlog:逻辑日志,负责主从复制和归档恢复
  • 物理日志:记录数据页怎么改了
  • 逻辑日志:记录执行了什么变更操作
  • 不能只靠 binlog
  • 它不负责页级恢复
  • 它一般在提交时才写
  • 事务中途宕机兜不住

11. 两阶段提交

  • 两阶段提交是为了解决 redo logbinlog 的一致性问题
  • 避免主从不一致
  • 流程理解:
  • redo prepare
  • binlog
  • redo commit
  • 没有两阶段提交的后果
  • redo 成功但 binlog 失败:主库新,从库旧
  • binlog 成功但 redo 失败:主库旧,从库新

12. Spring 事务失效

  • 最典型:this 自调用绕过代理
  • 其他高频失效场景:
  • public 方法
  • 异常被吞
  • checked exception 默认不回滚
  • 对象不是 Spring 管理的 Bean
  • 数据库引擎不支持事务
  • 传播行为配置成非事务模式
  • 记一句:
  • 事务依赖代理,回滚依赖异常向外抛出

13. 常见 SQL 细节

  • count(*)count(1) 基本等价
  • 都会尽量走最小索引树统计
  • count(字段) 还要判断 null
  • 字段没索引时可能更重
  • delete 是 DML
  • 可回滚
  • 自增一般不重置
  • truncate / drop 偏 DDL
  • 通常不可回滚
  • truncate 清空数据并重置自增
  • drop 删除整张表
  • char 固定长度
  • varchar 变长
  • varchar 更省空间
  • 但更新变长时代价可能更高

14. 外键

  • 互联网项目通常不推荐物理外键
  • 原因:
  • DML 校验有性能损耗
  • 高并发下锁竞争和死锁风险更高
  • 分库分表演进困难
  • 工程治理和迁移成本高
  • 不用物理外键,不代表不要关联字段
  • 常见替代方案:
  • 逻辑外键 + 业务校验
  • 唯一索引 / 非空约束 / 状态机
  • 本地事务
  • MQ 最终一致性

15. 分页

  • 深分页慢的核心原因:
  • offset 很大时,前面大量数据都要先扫描再丢弃
  • 如果还伴随回表,成本更高
  • 常见优化方向:
  • 覆盖索引
  • 延迟关联
  • 子查询先拿 ID,再回表
  • 基于游标 / 上次最大 ID 分页

16. 主从复制

  • binlog 是主从复制基础
  • 主库写 binlog
  • 从库拉取并重放
  • 主从延迟常见原因:
  • 从库执行慢
  • 大事务
  • 锁冲突
  • 主库写入太猛
  • 读写分离后的坑:
  • 从库可能读到旧数据
  • 强一致读取场景要回主库或做一致性策略

17. 分库分表

  • 什么时候考虑:
  • 单表数据量太大
  • 单库连接 / IO / 存储扛不住
  • 写入压力太高
  • 分表主要解决:
  • 单表过大
  • 索引过大
  • 单表查询变慢
  • 分库主要解决:
  • 单机资源瓶颈
  • 连接数瓶颈
  • 写入吞吐瓶颈
  • 常见副作用:
  • 跨库事务复杂
  • 跨库 join 困难
  • 全局 ID、分页、排序都更复杂

18. 结合你项目必须会落的 MySQL 口径

  • 黑马点评
  • 索引、事务、Lua 预扣后的 MySQL 落库兜底
  • where stock > 0 的条件更新
  • 唯一约束怎么防一人一单 / 重复回调
  • 事务为什么不能 this
  • 为什么锁要包在事务外层
  • 苍穹外卖 AI 智能客服 Agent
  • 条件更新为什么能保证原子写
  • 唯一约束怎么做支付回调幂等
  • Redis 持久化状态和数据库真实状态怎么兜底
  • 高风险步骤怎么做事务边界和最终确认

19. 当前完成标准

  • 如果目标是常规后端一面 / 二面
  • 补齐上面 1 到 17,基本算 MySQL 主干完成
  • 如果目标是项目深挖
  • 还要继续补:
  • 慢 SQL 排查
  • 死锁定位
  • 主从延迟治理
  • 分库分表后的事务与分页问题