IT 论文精读 · PAPER 62

A Critique of ANSI SQL Isolation Levels(SQL 隔离级别批判)

Berenson, Bernstein, Gray, Melton, O'Neil, O'Neil · SIGMOD 1995

EN →

这篇论文干了什么?

数据库上有个旋钮叫隔离级别:它决定「同时进行的好几笔操作,彼此能干扰到什么程度」。拧紧了安全但慢,拧松了快但可能算错账。1992 年的 SQL 国际标准给这个旋钮定了四档,并用几句大白话说明每档防住了什么。1995 年,六位重量级人物(包括 SQL 标准的编辑本人,以及事务处理的奠基者 Jim Gray)写了这篇论文逐条拆穿:那几句大白话一句能读出两个意思,而且漏掉了好几种天天发生的事故。

先说个怪事

标准里对「脏读」的说明大意是:A 改了一行还没落定,B 就把它读走了,随后 A 反悔撤销——于是 B 读到了一个从未真正存在过的数字。听上去挺合理。

但论文指出:照这个字面读法,只有 A 最后反悔才算事故。那要是 A 没反悔、一路改完落定了呢?B 照样可能在「改到一半」的账本上读到错账——转账转了一半,钱从这头扣了、还没进那头,B 这时看过去,总额凭空少了一截,按字面读法却不算违规。同一句话,严的读法把这类情形全禁掉,松的读法只禁其中一种,而标准没说清自己是哪个意思。两种读法之间,隔着「你的钱会不会被算错」。

说明书还漏了什么

论文接着补上标准只字未提、现实里却常见的事故。一是两个人同时改同一处,后写的把先写的悄悄抹掉——这一类连最松那一档都必须防住,否则「撤销」本身就没法做对(你不知道该恢复成谁的旧值)。二是各自读了余额、各自加钱写回,一个人的更新凭空蒸发。

最阴的是第三类:两个人分别看了同一份账,各自做出看起来都合法的决定,合起来却把规矩破了。夫妻俩各持一张卡,银行规定两个账户加起来不能欠钱;两人同时查账,都看到「一共还剩一百」,于是一个从这边取八十、一个从那边取八十——各自都不越线,合起来欠了六十。谁也没读到脏数据,账还是烂了。

快照隔离:各看各的照片

论文还把一种当时已流行、却没被标准收录的做法整理清楚,正式命名为快照隔离。直觉是:每个人一进门,就先给整座图书馆拍一张照片;此后无论别人怎么搬书,你只看手里那张照片。所以读永远不必排队等人让开,也看不到别人搬到一半的样子。你的改动先记在自己名下,结账时柜台查一次:如果有人在你进门后动过同一本书、且比你先结完账,那就先结账的算数,你这一单作废重来。

这套办法又快又干净,前面的事故几乎全被挡住——但挡不住夫妻取钱那一种:两人动的是不同的书,柜台一查没撞车就都放行了,可他们依据的照片都已过期。

带来了什么

它把「隔离级别」从一段容易读歪的说明书,变成一份可以逐条对表的清单:每一档到底防住哪几种事故、放过哪几种,写得明明白白。今天数据库手册里的「脏读、不可重复读、幻读、丢失更新、写偏斜、快照隔离」,基本都出自这里。

一句话记住

标准用几句大白话定义隔离级别,既含糊(一句两读、宽严差着真金白银)又不全(漏掉真实事故)。这篇论文把每一档「到底防住什么」写成能逐条对照的清单,并给「各看各的快照、先结账者算数」这套做法起名叫快照隔离——顺带点破:它好用,却挡不住「各自都合法、合起来出事」的那一种。

想看那套精确记号、四类被漏掉的异常、以及为什么隔离级别根本排不成一条直线? → 切到精读版