写点什么

聊一聊事务的历史

  • 2018-04-19
  • 本文字数:2671 字

    阅读完需:约 9 分钟

本文最初发布于 Arjun Narayan 的博客,经原作者授权由聊聊架构翻译并分享。

我花了相当多的精力来理解数据库的事务,最近也与 Justin Jaffray 一起研究了该话题。本文总结了我们在这期间的所学。

数据库及分布式基础架构的相关社区花了数十年来理解事务的本质这一反复出现的问题。在阅读相关文献时需要读者理解其中的背景,不然就会被其中诸多矛盾的术语及认知所迷惑。为了澄清这点,下文阐述了数据库事务相关论述的演变过程。

在一开始(1990 年?),数据库连接还极其简单粗暴。在丛林法则下,没有行业标准的数据库与使用它们的程序员们必须处理许多异常现象。为了解决这些问题,ANSI SQL-92 标准首次尝试统一定义事务隔离级别。该标准选择了如下方式:

1. 存在一些已知的异常现象,即脏读不可重复读幻读
2. 可以利用一些锁策略来防止部分甚至全部上述的异常现象。它们被称为“读未提交”(不进行隔离)、“读已提交”(没有脏读)、可重复读(没有脏读及不可重复读)。
3. 最终的隔离级别避免了全部三种异常现象。它被称为可串行化(serializable),但是这和字面意思有些出入。暂且可以认为这是整个标准中的一个缺陷。

可串行化的历史相当久远。其定义可追溯到 20 世纪 60 年代,并通过 _ 事务中的历史记录 _ 来定义。 引用 Christos Papadimitriou 在一篇早期讨论事务的论文中所述:

可串行化是指,一系列原子性的用户更新、获取操作,且其全局的效果就像用户轮流,按一定顺序,独立执行各自的事务一样。

阅读该论文有一定难度,所以简单看来, Herlihy-Wing 已很好地解释了可串行化。但是其中的思想非常简单:每一个事务就像只发生在某一瞬间,而且它们之间存在一定的顺序(但并没有说其中的顺序对用户甚至事务本身需要明确!只需要事后可回溯)。

几年之后,微软数据库团队写了一篇名为《批判ANSI SQL 隔离级别》的论文,其中指出ANSI SQL 中定义的可串行化并不是真正的可串行化!ANSI 认为,只要消除了脏读、不可重复读和幻读,就是可串行化的。这一观点是不正确的。事实证明,如果消除这三种异常现象,得到的是另一种新的隔离级别,他们称之为快照隔离。

该论文另一个有价值的贡献是指出了,通过“是否存在特定的异常现象”来界定隔离级别并不是理想的方法。接着来讨论下事务的历史记录,这段时间的相关文献都是通过定义_ 特定的锁策略_,并证明其是否会产生异常现象来定义隔离级别的。这会带来一些困惑,因为同一隔离级别可以通过多种锁策略来实现,但其隔离级别的名称又与策略是相关联的,所以同一隔离级别会存在多个名称。

这时出现了一位大神来清理这一乱局:Atul Adya 与他的博士论文《弱一致性:一个通用理论和分布式事务的的乐观实现》。Adya 从追溯事务的历史记录开始。其策略基本上是“根据一些事务的历史记录,可以研究其中变量的转变图”,然后在图中标识出一些形状(其实大部分记录的是不同的周期),并表示“这其中存在问题”。然后,将这些问题的矛头指回到ANSI 的定义上,并可以追溯到ANSI 隔离级别的一些基础的数学定义中。该论文的巨大价值在于,终于可以精确且独立于具体实现锁策略地定义隔离级别!

除了给出四个ANSI 级别的定义之外,他还指出了其它更微妙的异常情况,例如 G2 ,又称“反依赖循环”,该情况很难被察觉,其存在于快照隔离和可串行化之间的未知领域中。

Adya 的论文在数据库领域是开创性的。这是第一次连贯地通过事务中变量的转变图来给出隔离级别的数学定义。当年是 1999 年,基础设施还不完善。

接下来出现了下一个问题:当我们对事务有了更多的理解后,我们应该如何处理现存的那些混乱的数据库(即 Oracle 和 Postgres,MySQL 至今仍然只是一个玩具产品)?它们声称实现了可串行化,但实际上只是实现了快照隔离,因为它们是按 ANSI 定义来构建的。

Alan Fekete 等人在 2005 年提出了一个好办法,他们称之为“让快照隔离可串行化”。基本上就是通过一个普通的快照隔离数据库,并在 SQL 语句中进行一些校验,以确保其可串行化。他们使用 TPC-C 作为运行示例,该系统已被明确设计为始终可串行化,即使在快照隔离数据库上运行时也是如此。一般应用开发程序员,即使被迫使用的是快照隔离数据库,也可以通过这个技巧得到可串行化的隔离级别。

有了这个好想法,Fekete 在 2008 年的一篇名为《快照隔离数据库上的可串行化隔离》的论文中对这项工作进行了扩展。论文基本上是以该想法为基础,并将那些检查代码从应用程序代码中迁移到了数据库上。因此,用户不必废除已有的事务处理引擎,只需要依赖额外的校验,从而让数据库可串行化。该技术被称为SSI(可串行化快照隔离),由于采用了两个技术定义,将它们结合起来重新命名一个全新的定义并不奇怪。

在2012 年,就有开发者决定将这个好想法在 PostgreSQL 上实现,从而让 Postgres 最终拥有可串行化隔离级别。注意,这并不是默认的 postgres 模式,因为 ANSI 认为快照隔离(但仍被称为可串行化)已经足够了。需要指出ANSI 的定义并没有被修复

该策略在一篇名为《批判快照隔离》的论文中得到了延续。文中指出,SSI 引导算法可以被简化。原始的SSI 算法检查双写冲突,为了扩展,Yabandeh 建议改为检测读写冲突。虽然这需要内存中的数据结构记录每次读取的最新时间戳的信息,但对于一些日常的负载来说,其具有更好的_ 并发控制_ 能力,因为它并不会中止读取操作,而只会中止写入操作。

也正是从此,大家开始意识到他们需要关心可串行性,一部分原因是 Jeff Dean 认为其非常重要。与此同时,持续呼吁该观点将近 20 年的 Michael Stonebraker 表示很无奈,大家显然只在 Google 明星工程师声明某件事的重要性时才会关心它。

当下学者们仍有很多焦虑,因为现在我们的处境非常尴尬

1. 根据理论,可串行化是唯一的选择
2. 很多人使用非串行化的数据库,但基本上并没有遇到问题?
3. 因此,我们是否在浪费时间?可串行化是否真的有必要?我们到底需要的是什么?

Peter Bailis 在 2014 年的一篇博文中总结了这一点。他说:

尽管存在诸多的弱隔离,但我还没遇到任何数据库架构师、研究人员或用户,可以解释何时以及为什么(这可能更重要)“读已提交”的隔离级别足以满足应用的正确执行。众所周知,这些弱隔离模型代表了“实践中的 ACID”,但我认为我们并没有真正了解为何大量的应用程序看上去(!?)可以在该级别下正确运行。

反面观点多认为:那样的应用并不总能保证正常运行,当你发现问题时,就可能已经太迟了,所以不要尝试。该论点也来之不易,在大家使用 NoSQL 数据库大约十年后,该观点才开始被关注。

查看英文原文: A History of Transaction Histories

感谢郭蕾对本文的审校。

2018-04-19 18:172670
用户头像

发布了 41 篇内容, 共 13.9 次阅读, 收获喜欢 3 次。

关注

评论

发布
暂无评论
发现更多内容

Docker下,极速体验pinpoint1.6.3

程序员欣宸

Java 分布式 4月月更

C语言总结_数组全方位练习

DS小龙哥

4月月更

小平邦彦:树懒style的世界一流数学家

图灵教育

数学 数学史 数学家

18 张图,一文了解 8 种常见的数据结构

爱好编程进阶

Java 程序员 后端开发

字节跳动构建Data Catalog数据目录系统的实践

字节跳动数据平台

数据库 字节跳动 数据治理 数据目录

微服务与领域驱动设计,架构实践总结

架构 微服务 领域驱动设计 软件架构

ThinkPHP6+swoole+easywechat使用教程

CRMEB

大数据培训Spark SQL底层执行流程

@零度

Sparksql 大数据开发

中国全球GPU市场竞争格局分析

Finovy Cloud

人工智能 gpu 云服务器

@RequestParam、@ModelAttribute、

爱好编程进阶

Java 程序员 后端开发

BS-XX-007基于JSP实现户籍管理系统

爱好编程进阶

Java 程序员 后端开发

想学习算法交易的工程师们,机会来啦~

非凸科技

rust 招聘 基金 量化交易 算法交易

基于语义感知SBST的API场景测试智能生成

华为云开发者联盟

测试 语义感知 SBST 动态修正 ODG图

2021最新分享Java面试题库万字精华 github上标星80

爱好编程进阶

Java 程序员 后端开发

2021最新一次Java面试,快手三面一轮游,如今已拿意向书

爱好编程进阶

Java 程序员 后端开发

想从单体架构演进到分布式架构,SBA 会是一个不错的选择

华为云开发者联盟

架构 微服务架构 分布式架构 单体架构 SBA

别再用老版云效Projex项目协作了,该升级了

阿里云云效

阿里云 项目管理 研发团队 项目协作 项目协作工具

一种很爽的学习方法,被我Get到了!

博文视点Broadview

13W字!2021最新发布互联网大厂高频面试技术点!

爱好编程进阶

Java 程序员 后端开发

《Mybatis 手撸专栏》第6章:数据源池化技术实现

小傅哥

Java 面试 小傅哥 mybatis 源码学习

微信小程序开发系列 (四) :微信小程序的页面跳转路由设计

汪子熙

微信小程序 微信 前端开发 微信开发 4月月更

2021最新Java学习路线,自学者的福利

爱好编程进阶

Java 程序员 后端开发

20 数据存储服务器集群的伸缩性设计

爱好编程进阶

Java 程序员 后端开发

企业文档协作如何进行?

小炮

文档协同

20年最新金九银十面试必备,教你一份文档吊打面试官,拿到offer

爱好编程进阶

Java 程序员 后端开发

大规模并行分布式深度学习

阿里云大数据AI技术

人工智能 深度学习 并行分布式训练

自己动手写 Docker 系列 -- 6.5 启动时给容器配置网络

Go Docker 4月月更

Spark SQL 字段血缘在 vivo 互联网的实践

vivo互联网技术

大数据 spark Sparksql 数据处理

聊聊Kotlin中的lambda

北洋

kotlin Andriod 4月月更

28岁程序身价过亿,从字节提前“退休

爱好编程进阶

Java 程序员 后端开发

聊一聊事务的历史_数据库_Arjun Narayan_InfoQ精选文章