阶段3(下):RAG、向量数据库专题;接入 BOSS直聘调研(research/、岗位对照和延伸技术栈);新增 cs 领域和 12 个技术栈骨架;面试题全部补齐追问并加入校验
This commit is contained in:
1 parent
7f52513ffc
commit
6650f7eb6d
52 files changed
+2777
-38
No files matched your search
@@ -20,6 +20,8 @@ week: [2, 14, 16]
|
||||
|
||||
**参考答案**:B+ 树的非叶子节点只存键,一个页能放更多键,树更矮,磁盘 IO 次数少;所有数据在叶子节点且叶子之间用链表相连,范围查询和排序高效。红黑树是二叉树,数据多时太高;哈希只支持等值查询,不支持范围和排序。
|
||||
|
||||
**追问**:一棵 3 层的 B+ 树大约能存多少行?→ 粗略估算:16KB 页,非叶子节点每条约十几字节,可放一千多个指针;叶子页按每行 1KB 放 16 行,约 1000 × 1000 × 16 ≈ 两千万行。这是数量级估算,实际取决于行大小。
|
||||
|
||||
### 【基础】什么是聚簇索引、回表和覆盖索引?
|
||||
|
||||
**参考答案**:InnoDB 的主键索引叶子节点存整行数据,叫聚簇索引;二级索引叶子节点存索引列和主键值。通过二级索引找到主键再去主键索引取整行叫回表。如果查询需要的列都在二级索引里,就不用回表,叫覆盖索引(EXPLAIN 的 Extra 显示 Using index)。
|
||||
@@ -30,42 +32,62 @@ week: [2, 14, 16]
|
||||
|
||||
**参考答案**:联合索引 `(a, b, c)` 先按 a 排序,a 相同再按 b,依此类推。查询条件要从 a 开始连续使用才能利用索引定位;只用 b 或 c 用不上;中间遇到范围条件(如 `a > 1`)后,后面的列一般不能再用于定位(可以靠索引下推过滤)。
|
||||
|
||||
**追问**:`WHERE b = 1 AND a = 2` 能用上 (a, b) 索引吗?→ 能,优化器会调整条件顺序;最左前缀看的是条件中是否包含最左列,不看书写顺序。
|
||||
|
||||
### 【基础】有哪些常见的索引失效情况?
|
||||
|
||||
**参考答案**:索引列上用函数或运算;隐式类型转换(字符串列用数字比较);`LIKE` 以 `%` 开头;不满足最左前缀;`OR` 连接的列有的没索引;优化器判断走索引不如全表扫描(区分度低、要扫的行太多)。
|
||||
|
||||
**追问**:怎么确认索引有没有用上?→ 用 `EXPLAIN` 看 `type`、`key`、`rows`、`Extra`;MySQL 8.0.18+ 可以用 `EXPLAIN ANALYZE` 看实际执行情况。
|
||||
|
||||
### 【基础】redo log、undo log、binlog 分别是什么?
|
||||
|
||||
**参考答案**:redo log 是 InnoDB 的物理日志,记录“某页做了什么修改”,保证崩溃后已提交的事务不丢(持久性);undo log 记录修改前的值,用于回滚和 MVCC 读旧版本(原子性、隔离性);binlog 是 Server 层的逻辑日志,用于主从复制和按时间点恢复。redo log 和 binlog 用两阶段提交保证一致。
|
||||
|
||||
**追问**:为什么需要两阶段提交?→ redo log 和 binlog 是两份日志,必须保证一致:否则崩溃恢复后主库数据和从库(通过 binlog 复制)不一致。
|
||||
|
||||
## 进阶
|
||||
|
||||
### 【进阶】InnoDB 的可重复读是怎么实现的?能解决幻读吗?
|
||||
|
||||
**参考答案**:普通 SELECT 是快照读,事务第一次读时生成 Read View,之后一直用它判断数据版本是否可见,所以多次读结果一致,也看不到别人新插入的行。当前读(`FOR UPDATE`、`UPDATE`)读最新数据,通过临键锁(记录锁 + 间隙锁)阻止其他事务在范围内插入,从而避免幻读。但如果事务里先快照读、再当前读,仍可能看到不一致,所以不能说“完全解决”。
|
||||
|
||||
**追问**:间隙锁会带来什么问题?→ 锁住的范围比实际修改的行大,并发插入会被阻塞,也更容易死锁;如果业务能接受,可以使用读已提交隔离级别减少间隙锁。
|
||||
|
||||
### 【进阶】什么情况下会死锁?怎么排查和避免?
|
||||
|
||||
**参考答案**:两个事务以不同顺序锁定相同的资源,互相等待。InnoDB 会检测并回滚代价小的那个事务(错误 1213)。排查:`SHOW ENGINE INNODB STATUS` 的 LATEST DETECTED DEADLOCK 段,看两个事务各自持有和等待的锁。避免:固定加锁顺序(如按 id 排序)、缩小事务、更新条件走索引减少锁范围、必要时降低到读已提交减少间隙锁;应用层捕获死锁并重试。
|
||||
|
||||
**追问**:死锁发生后 MySQL 怎么处理?→ InnoDB 检测到死锁后回滚代价较小的事务,另一个继续执行;应用层要捕获死锁错误并重试整个事务。
|
||||
|
||||
### 【进阶】主从延迟的原因和处理方式?
|
||||
|
||||
**参考答案**:原因:大事务、从库重放并行度低、从库负载高或配置差、网络。处理:拆分大事务、开启并行复制、关键读走主库(写后一段时间内读主库)、监控延迟超过阈值时把读流量切回主库。
|
||||
|
||||
**追问**:刚写入就读不到,业务上怎么处理?→ 写后立即读的请求走主库(或一段时间内该用户的读走主库);或者前端直接使用写接口的返回结果。
|
||||
|
||||
### 【进阶】什么时候需要分库分表?分片键怎么选?
|
||||
|
||||
**参考答案**:单表数据量大到索引优化后仍然慢、或单库写入成为瓶颈,并且归档、缓存、读写分离都用过之后再考虑。分片键选最常用的查询维度(如用户 ID),让大部分请求只访问一个分片,并且数据分布均匀。代价是跨分片查询、分页、事务、全局 ID 和扩容迁移都变复杂。
|
||||
|
||||
**追问**:分库分表后跨分片查询怎么办?→ 尽量通过分片键路由;后台统计类查询同步到 ES 或数仓;避免跨分片 JOIN 和分布式事务。
|
||||
|
||||
## 场景题
|
||||
|
||||
### 【场景题】“先查库存再扣减”在高并发下超卖了,怎么改?
|
||||
|
||||
**参考答案**:查和扣两步之间有并发窗口。改成一条条件更新:`UPDATE stock SET num = num - 1 WHERE sku_id = ? AND num >= 1`,判断影响行数;或者 `SELECT ... FOR UPDATE` 加锁后再扣。并发非常高时(秒杀),数据库行锁会成为瓶颈,在 Redis 里预扣库存、消息队列异步落库(见 Redis 专题的库存场景和跨栈场景“秒杀”)。
|
||||
|
||||
**追问**:用乐观锁还是 `UPDATE ... WHERE stock >= 1`?→ 扣库存这种只需要一个条件的场景,直接条件更新最简单;需要读出数据做复杂计算后再写入的,用版本号乐观锁。
|
||||
|
||||
### 【场景题】一张几千万行的表,分页越往后越慢,怎么优化?
|
||||
|
||||
**参考答案**:`LIMIT offset` 需要扫描并丢弃前面的行。改为游标分页(记住上一页最后一条的排序键和 id);需要跳页时用延迟关联并限制最大页数;导出走异步任务;历史数据归档。详见[深分页场景](scenarios/deep-pagination.md)。
|
||||
|
||||
**追问**:用户要求可以跳转到任意页,怎么办?→ 深分页限制最大页数;或者用延迟关联(先在覆盖索引上查主键,再回表);超深分页的需求通常可以引导为搜索 / 筛选。
|
||||
|
||||
### 【场景题】线上一个接口突然变慢,数据库 CPU 很高,你怎么排查?
|
||||
|
||||
**参考答案**:先 `SHOW PROCESSLIST` 看正在执行的慢语句和状态(是否大量 Waiting for lock);查慢查询日志按总耗时排序;对可疑 SQL 做 EXPLAIN,看是不是最近上线的新语句、索引被删、统计信息不准导致走错索引;有锁等待时查 `information_schema` / `performance_schema` 中的锁信息找到阻塞源。处理上可以先限流或下线问题功能止血,再加索引或改 SQL,最后复盘加监控。
|
||||
|
||||
**追问**:怎么防止慢查询再次发生?→ 上线前审查 SQL 和 `EXPLAIN`;开启慢查询日志并告警;对大表的变更进行评审。
|
||||
Reference in new issue
Block a user