Page 244 - 《软件学报》2026年第1期
P. 244
彭泽顺 等: 面向跨地理区域联盟链的事务处理技术综述 241
在排序阶段, 排序服务由多个排序节点构成, 并使用 Raft 等共识协议. 排序服务只负责打包并共识区块, 而区
块内交易的合法性稍后由 Peer 在验证阶段进行检查. 排序服务的主节点负责打包区块并进行 Raft 共识, 而从节点
收到的交易会转发给主节点. 在共识完成后, 所有排序节点都拥有所有未执行的区块.
在验证阶段, Peer 从排序服务按序拉取区块. 在验证区块和区块内交易的合法性后, Peer 按照交易在区块内的
顺序串行验证这些交易读的记录 (Key) 是否已经被其他交易修改. 若交易不存在读旧数据异常并通过验证, Peer
将该交易标记为有效并将修改写入状态数据库, 否则标记为失效交易. 在验证完毕区块内所有的交易后, Peer 告知
用户交易的执行结果.
虽然 Fabric 的执行流程简单高效, 但是其存在诸多问题. 例如交易并发修改热点数据会导致高终止率. 这是因
为在 OCC 执行流程中, 交易执行后会等待一段时间才能验证, 在此期间内, 交易所有读的记录不能被其他并发交
易修改, 否则会产生异常需要终止, Fabric++和 Fabric#针对该问题提出了重排序技术, 即通过改变交易的验证顺序
减少因为读写冲突终止的交易. Fabric++针对块内的冲突交易, 在原始的排序阶段前, 用有向图的方式来表示一个
块内的交易冲突情况, 通过剔除图中环上出现最多的交易来达成可串行化调度. 这样不仅减少了不必要的冲突终
止次数, 还提前在排序阶段而不是在验证阶段终止交易. 除此之外, 虽然交易可以并发执行, 但 Fabric 的交易验证
阶段是串行进行的. 为此, FlexChain 对交易做确定性的并发验证提升性能. Fabric#和 SlimChain 进一步利用 SSI
验证交易 (见第 2.2 节), 避免串行提交造成的瓶颈.
2.2 基于依赖图的并发控制
依赖图 (dependency graph) 映射了不同事务间的依赖关系, 使系统能够有效地识别并发执行事务时可能出现
的冲突和依赖. 基于依赖图的并发控制可分为两种, 已知事务读写集和未知事务读写集的并发控制. 如果事务的读
写集已知 (即事务在构建依赖图前已经完成执行), 系统可以快速根据读写集构造区块的完整或部分的读写依赖
图, 例如 Fabric# [105] 、文献 [104]、SlimChain [106] 和 XOXFabric [107] . 若构建依赖图时事务读写集未知, 可以通过推测
执行 [108] 、预执行 [109] 和代码分析 [110] 等技术, 在获得读写集后构建依赖图, 例如 FISCO-BCOS [27] . 最常用的使用依
赖图的并发控制算法为快照隔离 SI 和可串行化快照隔离 SSI [111] .
快照指的是在写操作时, 不在原本的值上修改, 而是创建一个新的版本. 读操作会读取最近提交成功的版本数
据. 快照隔离是并发控制的另一种方法, 它利用了每个数据项的多个版本, 每个事务所看到的数据库状态是在他开
始之前提交的所有事务产生的. 快照隔离 SI 可以解决可重复读级别的问题, 但因为存在写倾斜 [112] 问题, 其达不到
可串行化隔离级别. 写倾斜指在并发控制过程中, 多个事务对资源进行更新操作, 由于隔离性导致更新操作丢失.
可串行化快照隔离 SSI 是在快照隔离 SI 基础上支持可串行化. SSI 在数据库的版本快照上并发执行多个事
务, 通过依赖图检测的方法保证事务的可串行化.由于区块链以批处理的形式并发更新账本, SSI 天然适合用在区
块链系统上. 依赖图中的事务存在 RW、WR、WW 这 3 种关系 [112] . RW-反依赖为交易 T 1 先更新记录 A, 随后交
T 2 读了记录 A T 1 执行; WR T 1 先更新了记录 T 2 读了记
易 的旧版本, 此时等价执行顺序为 T 2 先于 依赖为 A, 随后
录 A 的版本, 此时等价执行顺序为 T 1 先于 T 2 执行; WW 依赖为 T 1 先更新了记录 A, 随后 T 2 在 T 1 的基础上更新记
录 A, 此时等价执行顺序为 T 1 先于 T 2 执行. 因此, 若依赖图中存在环, 则无法保证可串行化.
Fabric# [105] 将 SSI 引入到区块链用于在排序阶段检测交易的读写依赖, 进行重排序以提交更多的交易. 其将
SSI 定义的这 3 种依赖关系与两交易的并发关系结合, 定义了 6 种读写依赖关系, 其中, n-ww、n-wr、n-rw 这 3 个
依赖关系存在于非并发交易间, c-ww、c-rw、anti-rw 存在于并发交易间. 在这些依赖中, 只有存在 anti-rw 依赖的
交易会产生异常, 例如: 交易 T 1 进行对记录 A 的写操作的同时交易 T 2 开始对 A 的读操作. 后来由于交易 T 1 先于
交易 T 2 提交, 导致 T 2 读到了 A 的旧版本 (stale read).
在 Fabric#的排序过程中, 排序服务主节点可以通过分析读写依赖图判断交易是否能被提交. 与 Fabric++类似,
检测图中依赖成环和冲突而不能提交的交易, 并通过剔除不能提交的交易并通过重排序提高交易提交率. 由于排
序阶段已经剔除所有冲突交易, Fabric#的验证阶段不需要串行进行, 节点在收到区块后可以直接并发提交交易, 更
新状态数据库. 但是, Fabric++和 Fabric#需要为区块内交易构建依赖图. 由于构建图的复杂度高, 当区块内交易数

