mysql-internals · git:20260920.a4843f5 · 2026-09-20 · sha256 2f796490157bc19a

mysql-internals git:20260920.a4843f5A

Immutable. This exact content is served forever at /api/v1/blob/2f796490157bc19a.

---
name: mysql-internals
description: 数据库深挖:索引与存储结构、事务与 MVCC、锁与死锁、执行计划、复制与高可用、分库分表、NoSQL 选型。
keywords: [mysql, innodb, 数据库, 索引, b+树, 事务, mvcc, 隔离级别, 死锁, 执行计划, 慢查询, 主从复制, 高可用, 分库分表, lsm, redis, nosql, dba, 连接池]
layer: detail
domains: [backend, data-engineering]
---

## 面试官在意什么

数据库是后端面试里最容易问深、最能分出层次的一块:从"加个索引"到"页分裂与 change buffer",从"用事务"到"ReadView 与 undo 版本链"。面试官从业务现象切入(慢查询、死锁、主从延迟、误删、连接池耗尽),追到机制层;DBA 与内核岗再往存储引擎与优化器追。2026 年新增的追问是向量与全文检索进关系库(pgvector 之类)该不该用、什么规模顶不住。

## 项目 / 实习怎么深挖

简历上出现下面这类经历时从哪里切、追什么。追到候选人能说出机制、数字的来源与一次真实的故障或取舍才算实;只有框架名与结论、说不出自己那一段的,记为危险信号。通用的追问方法见 project-deep-dive。

- 简历出现 MySQL 调优 / 慢 SQL → 追执行计划怎么读、索引怎么改、改后前后数字、有没有因为统计信息或参数误判
- 简历出现主从 / 高可用 / 数据迁移 → 追复制延迟怎么处理、切换过没有、脑裂怎么防、迁移的双写与校验方案
- 简历出现分库分表 → 追分片键、跨片查询、扩过容没有、为什么不先做归档或读写分离
- 简历出现死锁 / 锁等待 → 追死锁日志怎么读、锁加在哪个索引上、业务怎么改
- 简历出现连接池 / 访问层 → 追池大小依据、实例数乘积、超时与重试
- 简历出现 Redis / MongoDB / ES → 追为什么选它、数据模型、一致性怎么保、出过什么事故

## 常见失守与危险信号

- 存储结构与索引:只知道"B+ 树"三个字;说不出回表与覆盖索引;主键用 UUID 却不知道页分裂
- 事务、隔离级别与 MVCC:把 RR 与 RC 混为一谈;说不出 ReadView 与 undo 版本链;长事务把 undo 撑爆不知道怎么查
- 锁与死锁:不知道锁加在索引上;读不了死锁日志;只会"重试"
- SQL 优化与执行计划:只会"加索引";不看执行计划;深分页用 offset 到几百万
- 主从复制与高可用:不知道复制延迟从哪来;切换靠人肉;不知道半同步的退化
- 数据库扩展与分库分表:一上来就分库分表;说不出分片键依据;不知道跨片事务与分页的代价
- 连接池与访问层:池大小随便填;不知道连接数是实例数的乘积;ORM 生成了什么 SQL 不看
- LSM、KV 与 NoSQL 选型:什么都放 MySQL 或什么都放 MongoDB;不知道 LSM 的写放大与读放大;Redis 大 key 与热 key 没处理过

## 常考主题清单

只列名字、阶梯与答实的标志,作"问到哪一层算实"的参考;问哪些、问几道由这份 JD 与这份简历定,不是配额。

### 数据库扩展与分库分表
- 阶梯:单库能撑多大、什么信号说明该拆了 → 读写分离的主从延迟怎么处理,垂直拆与水平拆的区别 → 分片键选错之后(热点、跨片查询、扩容重分布)怎么办 → 分库分表 vs 分布式数据库(TiDB 等)vs 换存储(宽表、ES)的取舍
- 答实的标志:先做过冷热分离/归档;分片键按主要查询维度选并接受次要维度走异构索引(ES/宽表/映射表);扩容方案有一致性哈希或成倍扩容的思路;主从延迟场景下有"写后读走主库"之类的处理

### 存储结构与索引
- 阶梯:为什么索引用 B+ 树、和 B 树的差别 → 聚簇索引与二级索引、回表与覆盖索引、页的结构 → 一张大表插入变慢、页分裂与碎片怎么观察与处理 → 主键选自增还是 UUID、什么场景该用 LSM 引擎(写放大与读放大的取舍)
- 答实的标志:能画出聚簇索引与二级索引的关系;知道页分裂、填充因子、change buffer;能对比 B+ 树与 LSM 的写放大与读放大

### 事务、隔离级别与 MVCC
- 阶梯:ACID 各靠什么机制保证;redo、undo、binlog 各解决什么 → RC 与 RR 的差异、ReadView 的生成时机、undo 版本链;两阶段提交的顺序与 crash 后的恢复规则 → 长事务导致 undo 膨胀怎么发现与处理;主从数据不一致怎么判断是哪一环 → 隔离级别选 RC 还是 RR 的业务依据;双 1 配置的性能代价与什么业务可以放宽
- 答实的标志:能说出 RR 下同一事务两次快照读一致的原因;知道 innodb_trx 与 history list length;能讲清 prepare、写 binlog、commit 的顺序与恢复判断;能按业务容忍度选刷盘策略

### 锁与死锁
- 阶梯:行锁、间隙锁、next-key lock、意向锁分别锁什么 → RR 下哪些语句会加间隙锁、唯一索引与非唯一索引的差异 → 一次死锁日志怎么读、锁等待超时怎么排查 → 减少锁冲突的业务改写与降到 RC 的取舍
- 答实的标志:知道锁加在索引上、无索引时锁全表;能读 SHOW ENGINE INNODB STATUS 的死锁段;有业务层顺序化或拆分事务的方案

### SQL 优化与执行计划
- 阶梯:执行计划里 type、key、rows、Extra 分别看什么 → 索引失效的常见原因、选择性与最左前缀、排序与分组走不走索引 → 一条慢查询的完整归因流程(索引、统计信息、锁、IO、参数) → 大表分页、count、深度 JOIN 的改写与何时该放弃在数据库里做
- 答实的标志:能读执行计划并解释每一列;知道数据分布、统计信息、参数、缓存热度的影响;有延迟关联、游标分页等改写

### 主从复制与高可用
- 阶梯:主从复制的三个线程与流程;binlog 格式、并行复制、GTID → 复制延迟持续增长怎么定位是大事务、DDL、单线程还是从库 IO;半同步的超时退化 → 一次主库宕机的处理时间线:切换怎么保证数据不丢、怎么防脑裂、旧主怎么处理;Online DDL 与大表变更工具的原理与副作用 → 跨机房与多活的成本;什么业务值得;什么时候该上分布式数据库而不是分库分表
- 答实的标志:能说出 IO 线程与 SQL 线程各自的瓶颈;知道 fencing 与 VIP/DNS 切换;有大事务拆分与 DDL 低峰执行的规范;迁移有双写、校验与回滚步骤

### 连接池与数据访问层
- 阶梯:为什么要连接池、池大小怎么定 → 连接数是实例数 × 池大小;数据库侧的上限与等待队列 → 接口偶发超时、"too many connections"、ORM 的 N+1 与隐式事务怎么从应用层排查 → 读写分离、缓存该由哪一层做;什么时候绕过 ORM 写 SQL
- 答实的标志:能算连接总数;有连接池耗尽的排查案例;知道 ORM 生成的 SQL 并看过执行计划

### LSM、KV 与 NoSQL 选型
- 阶梯:B+ 树与 LSM 各适合什么读写比;memtable、SSTable、compaction 与 bloom filter → Redis 持久化与主从、集群分片、大 key 与热 key;MongoDB、HBase、Elasticsearch 各适合什么数据模型 → 写放大、读放大、空间放大怎么度量;缓存与数据库不一致、Redis 内存打满、集群某节点慢怎么排查 → 什么数据该放数据库、什么该放缓存、什么该放搜索引擎;向量与全文检索进关系库的边界
- 答实的标志:能对比 B+ 树与 LSM 的放大;按数据模型与访问模式选型;知道 bigkeys / slowlog / hotkeys;有拆 key 或本地缓存方案