JJava 知识库
JAVA INTERVIEW

高频面试题

MySQL进阶约 3 分钟

订单状态更新和用户查询并发发生时,你们怎么选择隔离级别?MVCC 在里面起什么作用?

参考回答约 3 分钟 · 口语表达
先说结论

这个问题我会先说项目结论:从 ACID、Read View、Undo Log 到当前读和间隙锁系统理解事务

01

我会先交代项目背景和选型结论。从 ACID、Read View、Undo Log 到当前读和间隙锁系统理解事务。

02

具体落地时,我会沿着实际调用链来讲。沿着「事务分配标识 → 更新生成新版本与 undo → 读取建立 Read View → 沿版本链判断可见性 → 提交后 Purge 清理历史」观察输入、状态与输出,这些阶段都可以从日志、指标或源码里验证。 事务分配标识 InnoDB 事务开始与首次一致性读的时机受隔离级别影响,Read View 不一定在 begin 时创建。 storage/innobase/read/read0read.cc:Read View 可见性判断。 SHOW ENGINE INNODB STATUS:History List Length 与事务。

03

参数和容量不能靠默认值,我会结合业务量来定。保持一个长 RR 快照同时持续更新,观察 undo 历史、版本链读耗时和 Purge 恢复。

04

效果要用数据证明,线上问题也要能闭环。固定输入和基线 先在没有故障注入的环境执行上述配置,固定数据规模、并发度、运行时版本和预热时间。以「最长事务」为主基线,记录值应满足「在线请求秒级」;同时保存 活跃事务时长、History List Length,使后续变化能够回到同一时间轴比较。 只读报表保持事务数小时,线上更新持续产生 undo,History List Length 不断上升,磁盘和查询延迟恶化。把报表拆成短快照批次并在只读副本执行后,Purge 才能追上。 把快照读误认为完全无锁事务:活跃事务时长:终止异常长事务。 长事务阻塞 Purge:History List Length:报表拆短批次/副本。

05

最后我会主动说明这个方案不适合什么场景。方案:更适合的场景:主要收益:代价与边界。 READ COMMITTED:允许同事务两次读看到新提交:版本链压力较低、语义直观:不可重复读。 REPEATABLE READ:事务内需要一致快照:InnoDB 默认且配合 Next-Key Lock:长事务持有旧快照更久。 SERIALIZABLE/显式锁读:关键不变量需强串行:语义最强:锁竞争与吞吐成本高。