[面试题]在业务中你是根据什么选择不同的隔离级别的?
📖 版块 A:知识讲解版 (温故知新)
选型核心逻辑:在业务中选择隔离级别,本质上是在做一道**“并发性能/死锁概率”与“事务内数据静态一致性”**的单选题。
排除极端选项:
- RU(读未提交):存在脏读,业务绝对不可用。
- Serializable(串行化):强制排队,并发为零,仅在极端财务清算或数据全量备份时偶有使用。
业务中最常做的其实是RC和RR之间的选择:
-
选择 RC (Read Committed) 的考量(偏向吞吐与实时):很多大厂会将 MySQL 默认的 RR 改为 RC,以换取极致的并发吞吐量。
- 降低死锁率:RC 没有间隙锁(Gap Lock),极大降低了并发更新时的死锁概率。
- 实时性:每次读取都能拿到别人刚提交的最新数据,适合高频状态变更。
-
选择 RR (Repeatable Read) 的考量(偏向静态与严谨):
- 防幻读与不可重复读:适合复杂运算。
- 多表关联与报表:在长事务(注意区分**“大事务”和“长事务”**)中,确保第一条 SQL 和最后一条 SQL 看到的世界是一致的,防止数据自相矛盾。
🎤 版块 B:面试实战版 (高手逐字稿)
Q:在业务开发中,你是根据什么标准来选择不同的事务隔离级别的?
🧠 破局思路:这道题绝对不能背诵四种隔离级别的定义。面试官想听的是你在面临高并发业务时的权衡(Trade-off)。核心要打出两个点:一是为什么互联网公司偏爱 RC(为了少加锁、防死锁),二是为什么有些业务必须死守RR(为了长事务的快照一致性)。最后可以补充一句应用层的兜底方案,拉高回答维度。
💬 高手逐字稿:
在实际的业务架构中,我们基本不会考虑 RU 和串行化这两个极端。所以这个问题,本质上就是在 RC(读已提交)和 RR(可重复读)之间做取舍。
我选择的核心标准只有两个维度:并发锁冲突的容忍度 和 事务内数据的静态一致性要求。
如果这是一个典型的高并发业务,比如电商的订单系统、社交信息流,通常是大量的短事务和简单的 CRUD,我会毫不犹豫地选择 RC。
有两个原因:首先,RC 每次查询都能读到最新的已提交数据,实时性更好。更重要的是,RC 级别下 MySQL 不会使用间隙锁(GapLock),这就极大降低了由于并发更新引发的死锁概率。实际上,我们团队(或很多一线大厂)都会把 MySQL 默认的 RR 显式降级为 RC,以换取极高的并发吞吐量。
但如果业务场景切换到了后台的财务对账、涉及多张大表的复杂报表生成,或者包含多步校验的复杂状态机,我就会严格使用 RR。
因为在这些场景下,事务往往比较长。如果使用 RC,可能刚查完账户余额,准备入账时,余额被别的事务改了,这会导致严重的逻辑漏洞。RR
能够提供一个事务级别的“一致性快照”,确保我从事务开始到结束,看到的数据世界是静态不变的,这就从引擎层面上杜绝了不可重复读和幻读的风险。
最后总结一下:对于 90% 的高并发在线业务,我倾向于用 RC 提升数据库吞吐,如果偶尔遇到需要强一致性的落库操作,我会通过在应用层加分布式锁,或者在 SQL 级别用乐观锁、SELECT … FOR UPDATE来兜底;而对于那些决不允许数据中途变动、逻辑极度严谨的复杂交易和报表,我就交给 RR 来保证底层一致性。