boltdb 是市面上为数不多的纯 go 语言开发的、单机 KV 库。boltdb 基于 Howard Chu’s LMDB 项目 ,实现的比较清爽,去掉单元测试和适配代码,核心代码大概四千多行。简单的 API、简约的实现,也是作者的意图所在。由于作者精力所限,原 boltdb 已经封版,不再更新。若想改进,提交新的 pr,建议去 etcd 维护的 fork 版本 bbolt。
为了方便,本系列导读文章仍以不再变动的原 repo 为基础。该项目麻雀虽小,五脏俱全,仅仅四千多行代码,就实现了一个基于 B+ 树索引、支持一写多读事务的单机 KV 引擎。代码本身简约朴实、注释得当,如果你是 go 语言爱好者、如果对 KV 库感兴趣,那 boltdb 绝对是不可错过的一个 repo。
本系列计划分成三篇文章,依次围绕数据组织、索引设计、事务实现等三个主要方面对 boltdb 源码进行剖析。由于三个方面不是完全正交解耦的,因此叙述时会不可避免的产生交织,读不懂时,暂时略过即可,待有全貌,再回来梳理。本文是第三篇, boltdb 事务实现。
引子
在分析 boltd 的事务之前,我们有必要对事务概念做一个界定,以此来明确我们的讨论范围。数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成^1。wiki 上的定义有点拗口,理解时只需抓住几个关键点即可:
- 执行:计算层面
- 逻辑单位:意味着不可分割
- 操作序列有限:一般粒度不会太大
那为什么要有事务呢?事务出现于上世纪七十年代,是为了解放数据库用户的心智而出现的:事务帮助用户组织一组操作、并在出错时自动进行扫尾。后来,NoSQL 和一些分布式存储为了高性能而舍弃了完整事务的支持。然而,历史是螺旋上升的,事务的便利性让 NewSQL 等新一代分布式数据库又将其重新请回。
提起事务,最脍炙人口的便是 ACID 四大特性。 其实 ACID 更像一种易于记忆的口号而非严格的描述,因为他们在概念上并不怎么对称,而且依赖于一些上下文阐释。本文仍然会按照这四个方面对 boltdb 对事务的支持进行剖析,但在每个小结开始,会先参考 Martin Kleppmann 的演讲[^2],试着从不同角度先阐释其内涵;然后在再分析 boltdb 对其实现。




