八股 ②:事务、隔离级别、锁、MVCC 20 问
接着攻克面试最容易讲糊的一片区。好消息:你 W5 用两个 psql 窗口真刀真枪复现过每一种异常。
学 · 20 min
练 · 100 min
- 整理 20 题并写口述稿
参考答案
题单方向:ACID 各自靠什么实现(原子性靠 WAL、隔离靠 MVCC+锁);四个隔离级别 × 三种异常的矩阵;脏读 / 不可重复读 / 幻读各是什么(幻读强调「查询结果的集合变了」);PG 默认 RC;PG 的 RR 靠快照、MySQL 的 RR 靠间隙锁;MVCC 的 xmin/xmax 与死元组回收;死锁四条件;乐观锁 vs 悲观锁。「幻读」和「两库 RR 差异」这两题单独各写一版 90 秒稿。
- 用 D34 实测出的表格作为讲述时的证据
参考答案
讲述句式:「这个我在两个 psql 窗口里真实复现过:窗口 A 先执行……,窗口 B 再执行……,实际结果是……」。实测表格是证据不是背诵,面试官一听就知道你动手做过,比背八股高一档。
- 录音回放并修正
参考答案
回放标准同 D50,这区额外重点查「幻读」的解释有没有绕圈子--绕就是定义没钉死,回去用一句话定义(「同一查询在事务内两次执行,结果的行集变了」)重写再录。
- 练习画图讲解 MVCC 的可见性判断
参考答案
一张图画三层:① 表里同一行的多个版本(每版标 xmin/xmax);② 事务快照(记下哪些事务对我可见);③ 可见性判断流程(先看 xmin 是否在快照内,再看 xmax 是谁删的)。练到 2 分钟内边画边讲完,笔不停。
- 准备「你遇到过死锁吗」这类经历题的答案(用 D35 的实验当素材)
参考答案
经历题用 STAR 四句:情境(业务场景一句话)、任务(要排查什么)、动作(怎么用两个窗口复现、怎么定位到锁顺序)、结果(怎么防:统一加锁顺序 / 缩短事务)。如实说这是实验复现,会做实验本身就是加分项。
今日复盘
- 把页面底部「性能与索引」8 问 + 自己补 12 问,写成 20 题
参考答案
页面 8 问之外,自补 12 问按三类分:① 原理(B-tree 为什么快、PG 的索引与堆是什么关系);② 失效场景(列上套函数、前导 % 模糊、<>、类型不匹配);③ 实战(EXPLAIN 怎么读、cost 估算和 actual 偏差说明统计信息过期、三种 join 算法的选择依据、索引的写放大代价)。每题先写一句话答案钉住结论,口述稿再扩。
- 用唯一索引 +
ON CONFLICT DO NOTHING实现幂等下单参考答案
只有第一次 returning 返回 id(= 抢到),之后每次都返回 0 行=重复请求在数据库层被无声吞掉。幂等键的颗粒度是业务定的:用户+活动还是用户+商品,想清楚再建。
-- 秒杀订单表:幂等键 = (user_id, activity_id),一人一单 create table seckill_orders ( id bigint generated always as identity primary key, user_id uuid not null, activity_id int not null, created_at timestamp not null default now(), unique (user_id, activity_id) ); -- 同一用户连点五次 = 同一条语句发五遍,连跑五遍看效果 insert into seckill_orders (user_id, activity_id) values ('00000000-0000-0000-0000-000000000042', 1) on conflict (user_id, activity_id) do nothing returning id; select * from seckill_orders; -- 无论跑几遍,永远只有一行 - SELECT * 的三项代价
易错点
select * 还会破坏 prepare 语句的缓存效果(结构一变计划全重算)。