并行 EVM 讨论里反复出现同一套动词:先并行执行,再检查冲突,不行就回滚重跑。这听起来像链上原创,骨架却来自数据库。1981 年,H. T. Kung 与 John T. Robinson 在 ACM TODS 发表《On Optimistic Methods for Concurrency Control》,把「乐观」写成可分析的并发控制方法。读懂那套逻辑,再看 Block-STM 或并行 EVM 引擎,会少很多神秘感。
本稿用数据库视角讲清 OCC 的假设与三阶段,把它和悲观锁、MVCC 分开,然后说明区块链借用骨架时多了哪些约束。这是理解「为什么乐观并行适合 EVM 兼容路线」的前置课,而不是任何具体产品的参数手册。
乐观在赌什么
传统并发控制大量依赖锁:访问前加锁,防止别人同时改你正在读的数据。锁能保证正确,但维护锁表、检测死锁、长事务占锁拖垮队列,都会在高并发下变成明显开销。OCC 的反直觉提议是:若大多数事务的读写集合其实并不重叠,不如先让它们跑,把冲突检查推迟到提交前夕,避免为「可能永远不发生的冲突」支付锁成本。论文把回退(backup)当作主要控制手段——「乐观」指的是寄希望于冲突稀疏。
这不是否认冲突存在,而是转移处理时机:从执行前预防,改为执行后(或临近提交时)验证。时机一变,系统设计的主矛盾就从「如何精细加锁」变成「如何便宜地检测冲突、如何缩小重做范围」。
读、验证、写:三阶段骨架
经典 OCC 把事务拆成三个阶段。
读阶段:事务自由读取数据库,写入只落在私有工作区,不立即污染共享状态。对观察者而言,未验证事务的副作用尚不可见,或仅以隔离方式存在。
验证阶段:事务获得时间戳或序号,系统检查其读集是否仍然有效——是否在读取之后被「按顺序应排在前面」的其他事务改写。若读集过期,验证失败,事务中止并重来。验证要回答的问题本质是可串行化:并行执行的交错,能否等价于某个串行顺序。
写阶段:验证通过后,把私有写集合并进共享数据库。论文还区分串行验证与并行验证:前者把验证与写入绑成更强的原子步骤,实现简单;后者允许更多并发,但需要额外机制保证不会写出互相矛盾的提交。
把这三阶段映射到区块链并行执行,几乎是一一对应:交易在推测状态下执行并收集读写集;按区块内既定顺序验证;通过者提交状态,失败者按依赖重执行。名称可以叫 STM、Block-STM 或「乐观并行 EVM」,骨架仍是 OCC。
悲观锁为何显得重
两阶段锁(2PL)是关系数据库里最经典的悲观方案:事务持锁只增不减直到结束。正确性好讲,代价也好懂——锁内存、死锁、队列头阻塞。竞争低时,2PL 的「预防税」可能高于 OCC 偶发的重做;竞争高时,OCC 的重做风暴可能反超锁的成本。因此 OCC 从一开始就被标成「低争用更划算」。链上翻译是:当区块内交易读写集重叠少,乐观并行赚得多;当大家都打同一个 AMM 池,乐观并行必须靠工程把重执行限制住,否则数字会很难看。
这也解释了为何性能披露必须标明负载类型与测试条件。实验室里大量无关转账,与主网高峰期的 DEX 路由交易,冲突结构完全不同;同一套 OCC 引擎可以给出差一个数量级的观感。
MVCC:相关,但不是同一个旋钮
多版本并发控制(MVCC)常与 OCC 并列出现,却回答不同问题。MVCC 让读者看到一致性快照,读者不阻塞写者;核心是版本存储与可见性规则。OCC 核心是验证失败时怎么办。二者可叠加:用多版本降低读写互相踩踏,再用乐观验证决定写写冲突时谁提交。Hekaton、Silo、TicToc 等系统展示了时间戳、去中心化验证、延迟分配序号等变体,共同点是承认「纯悲观锁在多核上太贵」,用版本与延迟验证换吞吐。
对链上工程师,澄清有助于读论文与项目文档:有人说「我们用了 MVCC」,可能只描述状态表示;真正决定并行 EVM 行为的,往往是验证规则与重执行调度——那是 OCC 家族的问题。
区块链多出来的规则
数据库 OCC 通常假设失败可本地重试,客户端能感知中止。区块链多了两条硬约束。
第一,全网确定性重放。所有诚实节点对同一区块必须得到同一最终状态。乐观执行可以在节点内部并行,但提交结果必须收敛到与规范顺序等价的状态;不能出现「这台机器因调度运气不同而提交了另一套写集」。这迫使实现把「预设顺序」或「规范序号」写进协议,而不是让线程调度成为语义的一部分。
第二,拜占庭环境。不能假设单一执行者诚实。节点可能撒谎、省略、故意制造冲突以拖慢对手。因此并行执行引擎通常嵌在更大的共识与验证流程里:顺序先由共识确定,执行层负责高效且确定地算出状态根;轻客户端与全节点依赖的是可验证的最终状态,而不是某次乐观路径的中间猜测。
Aptos 团队在 Block-STM 相关论文中,把引擎明确放在 STM 与 OCC 传统上,并强调把「排序」从诅咒变成可利用的性能条件:顺序给定后,并行只是加速收敛到该顺序的手段。这一表述对并行 EVM 同样适用——EVM 交易本就活在「区块内有序」的世界里,OCC 是在服从该序的前提下抢多核,而不是取消顺序。
读写集:抽象简单,工程不简单
教科书里的读集、写集在 EVM 里对应账户余额、nonce、存储槽、偶发的日志与退款副作用等。粒度太粗(整合约当一个键)会制造假冲突,并行度被白白吃掉;粒度太细会让跟踪与验证成本上升。动态跳转、外部调用、代理模式让静态预分析不完整,这正是 EVM 难走确定性预声明的原因,也是运行时收集读写集成为默认策略的原因。
冲突后是重跑单笔、重跑依赖闭包,还是整批作废,决定尾部延迟。优秀的 OCC 实现把「验证失败」当成可预期的热路径来优化,而不是异常分支。这些细节属于具体引擎设计;对本入门文,只需建立判断力:看到并行 EVM 宣称高吞吐,先问冲突率假设与重执行策略,再问测试网或基准条件。
从直觉到下一篇定位
用数据库 OCC 读区块链执行,是为了把讨论从口号拉回可检验的机制:假设是什么、验证查什么、失败成本由谁承担。Bitroot、以及其他乐观并行 EVM 项目,差异往往不在「是否 OCC」——而在读写集如何抓取、冲突如何分层检测、共识是否与执行流水线解耦。下一篇会把镜头对准 Bitroot:在扩容地图与三条并行路线上,它选了哪一格,边界在哪里,以及哪些承诺仍应标成测试条件下的工程目标。
