本文打算探讨 ACID 中的 C,因为它的定位有些模糊。


1. 正文

学得比较杂的朋友都知道,数据库事务模型的 ACID 里有个 C,分布式的 CAP 理论里也有个 C,刚好中文又都翻译成 “一致性”,就让人很头大了。

这个在《数据密集型应用系统设计》里有详细的介绍[1],读完后就很清晰了:

CAP理论中,一致性一词用来表示线性化。
而在ACID中,一致性主要指数据库处于应用程序所期待的 “预期状态”。

更可贵的是,这本书解答了一个困惑我很久的问题,即 ACID 里面的 C,不是数据库可以保证的事情,应该是靠应用层来保证。原文如下[1]:

ACID中的一致性主要是指对数据有特定的预期状态,任何数据更改必须满足这些状态约束(或者恒等条件)。例如,对于一个账单系统,账户的贷款余额应和借款余额保持平衡。如果某事务从一个有效的状态开始,并且事务中任何更新操作都没有违背约束,那么最后的结果依然符合有效状态。

这种一致性本质上要求应用层来维护状态一致(或者恒等),应用程序有责任正确地定义事务来保持一致性。这不是数据库可以保证的事情:即如果提供的数据修改违背了恒等条件,数据库很难检测进而阻止该操作(数据库可以完成针对某些特定类型的恒等约束检查,例如使用外键约束或唯一性约束。但通常主要靠应用程序来定义数据的有效/无效状态,数据库主要负责存储)。

原子性,隔离性和持久性是数据库自身的属性,而 ACID 中的一致性更多是应用层的属性。应用程序可能借助数据库提供的原子性和隔离性,以达到一致性,但一致性本身本不源于数据库。因此,字母C其实并不应该属于ACID【注1】。

注1:Joe Hellerstein 曾经在文献7中评论,字母C只是为了使ACID这个缩略词听起来更为顺口,当时并非觉得这是件很重要的事情。

上文中提到的 “文献7” 是这篇论文:Theo Härder and Andreas Reuter: “Principles of Transaction-Oriented Database Recovery”。

“字母C只是为了使ACID这个缩略词听起来更为顺口,当时并非觉得这是件很重要的事情。”, 这个让人很无语,导致我在大学以及工作的好多年后都一直被它困惑着(这也说明我很菜,没有及时的穷根溯底,找到根源)。

说回这个 “C” 本身,对啊,数据库怎么会知道你的业务数据是不是一致的。关于 “C”,我们常用转账的例子来说明,甲给乙转账,转账前后,甲乙的金额相加是不变的。但是数据库怎么会理解这种业务层的逻辑,它根本就不知道 A 和 B 的账户要平衡,也不应该知道这些细枝末节的。

所以这个 “C” 只能靠业务层去保证,业务层要依赖数据库的 A I D 这三个属性去实现 “C”。


2. 参考

[1] [美]Martin Kleppmann. 数据密集型应用系统设计. 赵军平, 吕云松, 耿煜, 李三平. 北京: 中国电力出版社, 2018-9(1): 214.