2025-12-17
面试与规划
0

目录

为什么 MySQL 没有采用三色标记法来解决并发问题??
问题内核不同
并发问题的本质不同
技术实现上的差异
持久化与一致性要求
个人的思考与总结

今日面试时,面试官问到了 “三色标记法”,我得回答是根据垃圾回收的 可达性分析算法,在垃圾回收时进行的并发标记的处理,然后讲了实现思路,与G1垃圾回收器中采用 增量更新 解决的并发标记问题,说到其本质就是垃圾回收与应用运行时的一种并发处理,与 MVCC 并发事务类似,都是针对于并发下的处理。

其实我在这是进行的 埋点,希望面试官来问我 MVCC 机制,我接下打算结合日志体系如何保障事务 ACID 来吊打他,结果面试官转弯来问到 那并发事务中,为什么不采用增量更新的形式解决呢?

image.png

为什么 MySQL 没有采用三色标记法来解决并发问题??

当遇到这个问题时,我的脑袋都是懵的,在我的理解当中,这俩个虽然解决的问题类似,但是 内核不一样 啊,像垃圾回收的并发标记,是针对与堆内存中的垃圾对象进行标记,而如何判断垃圾对象是通过可达性分析的算法,根据引用是否可达,也就是 GC ROOTS 的对象引用链进行标记处理的。

再来看 Mysql 中并发事务的处理,采用了 MVCC 机制,其底层是通过 隐藏字段,rowId, 事务ID,回滚事务ID,undo log 回滚日志,Read View 读视图 3部分组成,具体实现就不过多陈述了,可以查看我得文章 《数据库 - 深入了解 Mysql 事务与并发控制》,MVCC 中是通过 Read View 控制了并发事务的可见性,保障了事务之间的隔离性。

两者对比,增量更新是在并发处理期间,存储对对象调整的并发标记,在并发标记完成后,根据当前快照进行一次增量更新的动作,就是重新扫描下变更的引用链与标记的对象;MVCC 是通过存储事务的版本链进行的实现,接下来我将结合自己的了解与 AI 进行深度分析一下。

问题内核不同

三色标记法是用于垃圾回收的,解决的是内存中对象回收的问题,确保不被引用的对象被正确回收,同时允许用户线程并发运行。

MVCC 在数据库事务中,是为了保证数据的一致性、隔离性,思考的角度是多个事务并发读写时,如何保证 ACID 特性,为数据创建多个版本,每个事务看到一致的快照

并发问题的本质不同

在垃圾回收中,并发问题主要在于标记对象的同时,用户线程可能改变对象的引用关系,导致漏标或误标。三色标记法通过跟踪引用变化来保证标记正确。

在数据库事务中,并发问题主要在于 多个事务对同一数据的读写冲突 ,需要解决 脏读不可重复读幻读 等问题。

MVCC通过版本控制来避免事务之间的直接冲突。

技术实现上的差异

三色标记法需要跟踪对象引用的变化,通常需要内存屏障(barrier)来捕获引用更新,这在垃圾回收器中是可行的,因为对象引用的更新是内存操作,可以由虚拟机监控。

在数据库中,数据的读写是通过事务进行的,数据库需要维护多个版本的数据,并决定每个事务应该看到哪个版本。这需要维护版本链,并根据事务的隔离级别和开始时间来选择版本。

持久化与一致性要求

垃圾回收关注的是内存管理,不需要考虑持久化,也不需要考虑多个操作之间的逻辑一致性(只关注对象是否被引用)。

数据库事务要求持久化,并且要求保证事务的原子性、一致性、隔离性和持久性(ACID)。MVCC 通过版本控制来实现隔离性,同时配合日志(如 redo logundo log)来保证原子性和持久性。

个人的思考与总结

虽然 三色标记法MVCC 都是处理并发问题的技术,但它们解决的问题领域和设计目标不同。

其中也存在相似之处,都是并发处理,都是基于快照,不同的是并发下解决的问题不同,所以思考维度不同,同样快照的实现也不同,三色标记的快照是整个内存的快照记录,而并发事务是针对于当前行数据的快照,而且还是个版本快照链路,为了异常是回滚事务使用。

提示

是的,并发事务下要思考回滚,还要思考 mysql 崩溃后的数据一致性问题,而 JVM 无需这些考虑

对于数据库系统,如果采用类似的三色标记法来处理并发事务,可能需要对每行数据的读写都进行跟踪,这可能会带来更大的开销,而且并不能直接解决事务隔离性问题。

总体来看,虽然三色标记法和MVCC都是处理并发问题的技术,但我们从解决问题的内核上,并发的要求上,持久化上,还有性能上对比来看,MySQL 采用 MVCC 来解决并发事务问题是最合适的。

本文作者:柳始恭

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!