Gray 1981 — 把"事务"提升为通用抽象
是什么
Gray 1981 是 Jim Gray 在 Tandem Computers 写的一份技术报告(TR 81.3),同年发表在 VLDB 第七届会议上。它第一次系统地把”事务”从数据库特定术语,抽象成所有数据管理系统都该用的通用概念。
日常类比:你在 ATM 上把钱从储蓄账户转到信用卡。你按下确认时,机器内部要做四件事——查余额、扣储蓄账户、加信用卡、写流水。万一中间断电了,你最不希望看到的就是”储蓄扣了但信用卡没加”。事务的承诺是:这四件事,要么全做、要么一件都没做——你看到的余额永远是合法的。
Jim Gray 把这个朴素的需求抽象成三个性质:原子性(atomicity)、持久性(durability)、一致性(consistency)。两年后 Härder 和 Reuter 加了 Isolation(隔离性),合起来就是大家熟悉的 ACID 四个字母。
为什么重要
不理解 Gray 1981,下面这些事都没法解释:
- 为什么 postgresql / mysql 默认会自动加锁加日志,付出 30% 性能代价也不肯关——因为 Gray 论证了”没有事务的并发更新必然出错”
- 为什么分布式数据库(spanner / cockroachdb / foundationdb)即使写到全球节点,对外接口仍然是”一个 BEGIN … COMMIT” —— 这就是 Gray 主张的”事务 = 通用抽象”
- 为什么 paxos / raft 这些共识算法把”提交”叫 commit、把”回滚”叫 abort —— 整个分布式系统术语表是 Gray 这一篇定下的
- 为什么微服务时代又冒出 Saga 模式 —— 因为 Gray 在原文最后一节就预言了”长事务”是经典 ACID 的死穴
核心要点
事务的三个性质(Gray 1981 原文版本):
-
原子性(Atomicity):要么全做完,要么一件没做。类比:婚礼仪式上牧师问”你愿意吗?“,两个人说”我愿意”才算婚礼成立——任何一方说”不”,整个仪式作废。代码里就是
BEGIN ... COMMIT,中间任何一步出错就ABORT。 -
持久性(Durability):一旦 COMMIT 完成,就算之后地震断电,结果也要在。类比:合同一旦签字盖章,事后撕毁也算违约。工程上靠预写日志(WAL)——把意图写到永久介质后再改主存。
-
一致性(Consistency):事务把数据库从”一个合法状态”搬到”另一个合法状态”。类比:账户余额永远不能为负数;转账前后两个账户总和不变。这条由应用约束 + DB 引擎共同保证。
第四个 Isolation(隔离性)由 eswaran-1976 已经数学化,但 Gray 1981 这篇没并列写进 ACI——是 1983 年 Härder/Reuter 总结时才加上 I 凑成 ACID。
Gray 还把数据库动作分成三类,这一分类比”三性质”还实用:
- Unprotected(不受保护):临时草稿、过程消息——崩溃后丢了无所谓
- Protected(受保护):常规读写——崩溃后必须能 undo 或 redo
- Real(真实):取款机吐钱、火箭点火——做了就改不了,必须延迟到 COMMIT 后再做
实践案例
案例 1:银行转账的事务包裹
BEGIN TRANSACTION; UPDATE accounts SET balance = balance - 100 WHERE id = 'A'; UPDATE accounts SET balance = balance + 100 WHERE id = 'B';COMMIT;逐部分解释:
BEGIN之后两条 UPDATE 进入”暂存区”——别人查 A 还是看到原余额- 万一第二条之前断电,重启时 DB 看到日志里有 BEGIN 没 COMMIT,会自动
UNDO第一条 - 只有
COMMIT写进日志且刷盘,转账才算定数
案例 2:NonStop 容错——把不可靠零件拼成可靠系统
Gray 论文第一个大案例:Tandem 公司用镜像磁盘 + 进程对做出年级别 MTBF 的系统。
- 单磁盘一年坏一次,镜像后两块同时坏的期望时间是 800 年
- 每个关键进程有 backup process,主进程死了 backup 接管
- 接管的难点是”接哪一刻的状态”——这是 Gray 引出事务概念的钩子:用事务的 abort+restart 替代手动 checkpoint
这套思路后来被 paxos / raft 系统化成”共识 + 日志复制”。
案例 3:两阶段提交的婚礼类比
跨多个节点的事务怎么”一起 COMMIT”?Gray 用了一个非常生动的类比:
阶段 1(PREPARE): 协调者问每个参与者"你 OK 吗?" 每个回 "I do"(准备好了,承诺不再单方面 abort)阶段 2(COMMIT): 协调者收齐 "I do" 后宣布"我现在宣布你们..." 把 commit 决定广播给所有参与者跟基督教婚礼一字不差——牧师问双方”你愿意吗”,都说”我愿意”才宣布”我现在宣布你们结为夫妇”。这就是 2pc 协议的雏形,今天每个分布式数据库都在用它的某个变种。
关键设计点:进入 PREPARE 阶段后,参与者放弃单方面回滚的权利——必须等协调者最终决定。这条”放弃自由”换来”集体一致”的设计哲学,后来在 paxos / raft 里化身为”投票后必须服从多数”。
踩过的坑
-
update-in-place 是个毒苹果:直接覆盖磁盘上的旧值省存储,但崩溃时旧值丢了无法 undo。Gray 主张要么用日志保留旧值,要么用”时间域寻址”保留多版本。今天的 MVCC(postgresql / cockroachdb)就是后者的工业版本。
-
死锁随并发度平方增长:Gray 引用自己 1980 年的分析——deadlock 频率 ≈ 并发度² × 事务大小⁴。今天高并发系统拒绝”长事务 + 多行锁”组合就是这条定律的工程后果。
-
长事务把锁卡死:旅行社订票场景里,从客户问询到出票可能跨几小时。如果整段都开事务,锁会卡住后端所有人。Gray 在原文最后一章就承认这是 ACID 的死穴,提议”放宽一致性”,后来演化成 1987 年的 Saga 模式。
-
真实动作没法 undo:取款机已经吐出 100 元现金,事务事后 abort 也吐不回来。Gray 把动作分成 unprotected(草稿)/ protected(可撤销)/ real(不可逆)三类,real 动作必须推迟到 commit 之后再做——这是今天消息队列”恰好一次”语义的源头。
适用 vs 不适用
适用:
- 短事务 OLTP(银行转账、电商下单、库存扣减)—— 持续毫秒级、影响行数少
- 单机或同机房集群—— 锁延迟低,2PC 协调代价可接受
- 强一致性诉求场景(金融、医疗、票务)
不适用:
- 跨秒级以上的工作流(订单履约、报销审批、跨服务编排)—— 用 Saga 加补偿事务替代
- 跨大洲分布式(spanner 用 TrueTime 优化、但本质还是放宽延迟容忍)
- 高吞吐分析型场景(OLAP、日志聚合)—— 用最终一致性 + 不可变存储(kafka / clickhouse)
历史小故事(可跳过)
- 1976 年:eswaran-1976 发表《On the Notions of Consistency and Predicate Locks》,把 isolation 数学化(serializability)。Gray 是合作者之一。
- 1980 年:Gray 在欧洲讲座里发表《A Transaction Model》(Springer LNCS V.80),第一次完整描述 BEGIN/COMMIT/ABORT 语义。
- 1981 年 6 月:Gray 在 Tandem 写下 TR 81.3《The Transaction Concept: Virtues and Limitations》,把 model + implementation + limitations 拼成 23 页综述。同年 9 月在 VLDB-7 宣讲。
- 1983 年:Härder & Reuter 在 ACM Computing Surveys 发表《Principles of Transaction-Oriented Database Recovery》,把 ACID 四字母敲定。从此 Gray 的 ACI + Eswaran 的 I 合体成为统一术语。
- 1987 年:Salem & Garcia-Molina 提出 Saga 模式,专门解决 Gray 在 1981 论文末尾点名的”长事务”问题。
- 1998 年:Jim Gray 因事务概念和数据库恢复研究获得图灵奖。
学到什么
-
抽象的复用价值最大:Gray 把”事务”从数据库特定术语推广到所有”容错状态变换”,这一抽象后来直接被分布式系统、操作系统、消息队列、文件系统都拿走了。给概念起对名字、画对边界,比写出某段实现代码影响远得多。
-
失败优先设计:论文反复强调”系统总会失败、人总会犯错”,所以应该让失败成为一等公民——
ABORT跟COMMIT同等重要。这套”先想最坏再写代码”的姿态贯穿了后来所有可靠系统的设计哲学。 -
类比是合法的工具:Gray 用婚礼仪式讲两阶段提交、用 Hansel and Gretel 撒面包屑讲日志、用合同法讲事务起源——一篇 23 页论文里日常类比占一半。理论搞不通时,先用日常生活搭一座桥让人理解。
-
承认不能解决的就承认:论文最后三节专门列出”现有事务做不到的事”——长事务、嵌套事务、跟编程语言集成。Gray 没硬讲完美,反而引出了后续 30 年研究方向。这种”指出未来”的诚实,比强行收束的论文有价值得多。
延伸阅读
- 论文 23 页 PDF:The Transaction Concept: Virtues and Limitations(Gray 自己的话最好读,几乎没有数学)
- 视频:Pat Helland — Standing on Distributed Shoulders of Giants(Pat 是 Gray 的同事,把这条思想线讲了 50 分钟)
- 配套阅读:Härder & Reuter 1983《Principles of Transaction-Oriented Database Recovery》——把 Gray 的工作整理成 ACID 标准
- 现代视角:Martin Kleppmann《Designing Data-Intensive Applications》第 7 章,把事务讲到 21 世纪
- Saga 模式原始论文:Salem & Garcia-Molina 1987《Sagas》—— 解决 Gray 在本论文末章预言的”长事务”难题
关联
- codd-1970 —— 关系模型给事务提供了”操作的对象”,事务概念给关系模型补上”怎么改而不出错”
- eswaran-1976 —— 把 Isolation/Serializability 数学化的姊妹篇,Gray 是合作者
- paxos —— 把 Gray 的 commit/abort 语义在分布式环境里做出来
- raft —— Paxos 的工程化,commit 语义直接继承 Gray 的定义
- spanner —— 用 TrueTime 把 ACID 推到跨大洲规模
- cockroachdb —— 开源版 Spanner,事务模型直接源于本论文
- foundationdb —— 用确定性模拟测试事务正确性的工业代表
反向链接
- aries-1992 —— ARIES 1992 — 数据库崩溃后怎么把账目对回来
- bernstein-1981-cc —— Bernstein 1981 并发控制综述 — 把分布式数据库的 20+ 算法整成两条主线
- clickhouse —— ClickHouse — 列式 OLAP 数据库
- cockroachdb —— CockroachDB — 分布式 SQL 数据库
- codd-1970 —— Codd 1970 — 关系模型奠基
- eswaran-1976 —— Eswaran 1976 — 串行化与谓词锁的源头
- gray-1978-notes —— Gray 1978 — 数据库操作系统讲义,事务/2PL/2PC/恢复一次讲完
- lampson-hints —— Lampson Hints — 把做系统的隐式品味写成 27 条经验法则
- mysql —— MySQL — 全球最流行关系数据库
- mysql-server —— mysql-server — 一个仓库装下整套 OLTP 引擎
- paxos —— Paxos — 分布式共识算法
- paxos-1998 —— Paxos 1998 — 古希腊议会寓言里藏的共识协议
- postgresql —— PostgreSQL — 工业级关系数据库
- raft —— Raft — 易理解的共识算法
- saga-1987 —— Sagas — 长事务拆成一串能”反向走回去”的小事务
- spanner —— Spanner — 全球分布式 SQL 数据库
- stm-shavit-touitou —— STM Shavit-Touitou — 把”加锁”改成”事务”的源头
- stonebraker-2010-sqlnosql —— Stonebraker 2010 SQL vs NoSQL — 慢的是老实现,不是 SQL