概述
作者:Stavros Harizopoulos, Daniel J. Abadi, Samuel Madden, Michael Stonebraker
联机事务处理 (OLTP) 数据库包含一系列针对 20 世纪 70 年代的计算机技术而优化的功能 —— 磁盘 B 树和堆文件、基于锁的并发控制、多线程支持等等。现代处理器、存储器和网络的进步意味着,今天的计算机与 30 年前的计算机大为不同,以至于现在许多 OLTP 数据库都可以放在主存储器,并且大多数 OLTP 事务可以在几毫秒甚至更短的时间内得到处理。然而,数据库架构几乎没有发生变化。
基于这一观察,我们研究了传统数据库系统一些有趣的变体,人们可以构建它们来利用最近的硬件趋势,然后我们使用一个事务处理数据库系统 (Shore) 来运行 TPC-C 基准程序的一个子集,并通过这个系统所涉及的主要组件的详细指令级分解来推测它们的性能。我们没有简单地剖析 Shore ,而是逐步地修改它,以便在每次功能删除或优化之后,我们都有一个(更快的)工作系统来完整运行我们的工作负载。总的来说,我们确定了可以解释原始性能存在大约 20 倍差异的开销和优化。我们还证明,现代(内存驻留)数据库系统没有单个的 “ 瓶颈 ” ,但日志记录、锁存、封锁、 B 树和缓冲区管理操作上花费了大量时间。
分类和主题词
H.2.4 [ 数据库管理 ] :系统 —— 事务处理;并发。
通用术语
测量、性能、实验。
关键词
联机事务处理、 OLTP 、主存储器事务处理、数据库管理系统架构。
- 前言
现代通用在线事务处理 (OLTP) 数据库系统包括一组标准功能:一系列用于表存储的磁盘数据结构(包括堆文件和 B 树),通过基于锁的并发控制支持多个并发查询,基于日志的恢复和高效的缓冲区管理器。人们开发这些功能来支持 20 世纪 70 和 80 年代的事务处理,那时的 OLTP 数据库比主存储器大很多倍,而运行这些数据库的计算机成本高达数十万到数百万美元。
如今的情况则完全不同。首先,现代处理器运行速度非常快,以至于很多 OLTP 事务的计算时间以微秒计算。人们只需几千美元就可以购买到主存储器容量为数 GB 的系统。此外,组织机构拥有由众多此类工作站组成的网络集群并不罕见,其中的存储器总容量以数百 GB 来计算,这足以将许多 OLTP 数据库放在随机存取存储器中。
其次,因特网的兴起和用于众多领域的各种数据密集型应用程序导致人们对类似于数据库的应用程序的兴趣越来越大,而这些应用程序没有全套的标准数据库功能。如今,操作系统和网络会议充满了针对 “ 类似于数据库 ” 的存储系统的方案,这些存储系统具有不同形式的一致性、可靠性、并发性、复制性和查询能力 [DG04, CDG+06, GBH+00, SMK+01] 。
这种对类似于数据库的服务的需求增长以及显著的性能改善和硬件成本的下降表明,人们可以构建大量有趣的替代系统,这些替代系统具有与标准的 OLTP 引擎所提供的功能完全不同的功能集。
1.1 可供选择的 DBMS 架构
显然,当一个数据库可以放在 RAM 时,针对主存储器优化 OLTP 系统是一个好主意。但是众多其他的数据库变体是可能存在的;例如:
无日志数据库。 无日志数据库系统可能不需要恢复,或者可能从集群中的其他站点执行恢复(如在 Harp [LGG+91] 、 Harbor [LM06] 和 C-Store [SAB+05] 等系统中建议的那样)。
单线程数据库。 由于 OLTP 数据库中的多线程在传统上对于慢速磁盘写入时的延迟隐藏十分重要,因此在内存数据库系统中,它并不那么重要。在某些情况下,一个单线程实现可能就已经足够了,尤其是在它能够提供优良性能的情况下。尽管人们需要
一种方法来利用相同硬件上的多个处理器内核,但虚拟机技术的最新进展提供了一种方法来使这些内核看起来像是独特的处理节点,同时不会产生大量的性能开销 [BDR97] ,这可能让这些设计具有可行性。
无事务型数据库。 很多系统并不需要事务支持。尤其是在分布式网络应用中,最终一致性通常比事务一致性更受欢迎 [Bre00, DHJ+07] 。而在其他情况下,例如,当所有的读取需要在写入之前完成时,轻量级事务可能是可以接受的 [AMS+07, SMA+07] 。
实际上,数据库社区内部已经提出了几个方案来构建具有部分或全部上述特性的数据库系统 [WSA97, SMA+07] 。然而,一个待解决的问题是,如果这些不同的配置被实际构建出来的话,它们的性能表现会有多好。这是本白皮书的中心问题。
1.2 测量 OLTP 的开销
为了理解这个问题,我们选择了一个现代开源数据库系统( Shore—— 参阅 http://www.cs.wisc.edu/shore/ ),并在 TPC-C 基准测试程序的一个子集上对它进行基准测试。我们在一个现代台式机上进行的初始实现每秒运行大约 640 个事务 (640 TPS) 。然后我们通过从引擎中逐一移除不同的功能来修改它,并在每一步进行新的基准测试,直到我们得到一个可以处理 12700 TPS 的查询处理代码的微内核。这个内核是一个单线程、无锁、不带恢复功能的主存储器数据库系统。在这个分解过程中,我们确定了四个主要组件,将它们移除后,系统的处理能力得到大幅改善:
日志记录。 汇编日志记录和追踪数据库结构中的所有更改导致系统性能下降。如果没有可恢复性需求,或者可恢复性可以通过其他方式(例如,网络上的其他站点)来实现,日志记录可能不再必要。
封锁。 由于对数据库结构的所有访问均由一个单独的实体(锁管理器)管理,传统的两阶段封锁会造成相当大的开销。
锁存。 在多线程数据库中,许多数据结构必须在被锁存之后才能被访问。移除这项功能并进入一种单线程方法后,性能受到显著影响。
缓冲区管理。 主存储器数据库系统并不需要通过一个缓冲池来访问页面,从而在每个记录访问时消除一个中间层。
1.3 结果
图 1 展示了这些修改的每一项如何影响 Shore 的底线性能(依照每个 TPC-C 新订单事务的 CPU 指令)。我们可以看到
底部虚线是有用的工作,通过在无开销的内核上执行事务来度量。
每一个子系统本身占总运行时的 10% 到 35% (此图的总高度代表 173 万个指令)。在这里, “ 手工编码的优化 ” 代表我们对代码进行的一系列优化,这些优化主要改善了 B 树包的性能。实际用来处理查询的指令(标记为 “ 有用的工作 ” ,通过我们在手工编码的主存储器 B 树包上构建的最小实现来度量)只有上述数据的 1/60 。 “ 缓冲区管理器 ” 下方的白色框代表我们移除所有功能之后的 Shore 版本,它仍然能够运行事务,但它使用的指令大约只有原始系统的 1/15 ,或者大约是有用的工作中的指令数量的 4 倍。在我们的实现中,额外开销归因于 Shore 的调用堆栈深度,以及我们不能完全去掉对事务和缓冲区管理器的所有引用。
图 1. 各种 DBMS 组件针对 TPC-C 新订单事务的指令数的分解。条形图的顶部是原始 Shore 的性能(主存数据库,无线程争用)。
1.4 本白皮书的贡献和组织结构
本白皮书的主要贡献在于: 1) 仔细分析时间消耗在现代数据库系统中的什么地方; 2) 仔细地测量现代数据库系统各种精简变体的性能; 3) 使用这些测量结果来推测人们能够构建的各种数据管理系统的性能,例如没有事务或日志的系统。
本白皮书其余部分的组织结构如下所述。在第 2 部分,我们将讨论可能很快被淘汰(或者已经被淘汰)的 OLTP 功能。在第 3 部分,我们将探讨 Shore DBMS (它是我们整个探索过程的起点),并描述我们进行的分解。第 4 部分含有我们使用 Shore 进行的实验。然后在第 5 部分,我们将使用测量结果讨论这对未来 OLTP 引擎的影响,并推测一些假设的数据管理系统的性能。我们将在第 6 部分介绍其他的相关工作,并在第 7 部分进行总结。
- 关于 OLTP 的趋势
如在前言中所述,大多数常见的关系型数据库管理系统 (RDBMS) 起源于在 20 世纪 70 年代开发的系统,并且包含诸如基于磁盘的索引和堆文件、基于日志的事务和基于锁的并发控制之类的功能。然而,自人们做出这些架构决策算起,已经过去 30 年了。与这些传统系统问世的时代相比,如今的计算世界已经大为不同;本部分的目的在于探索这些不同之处的影响。我们曾在 [SMA+07] 中进行过一系列相似的观察。
2.1 集群计算
当前一代的大多数 RDBMS 最初是在 20 世纪 70 年代为共享内存的多处理器设计的。很多厂商在 20 世纪 80 年代增加了对共享磁盘架构的支持。在过去的二十年里,我们已经见证了类似于 Gamma 的无共享数据库 [DGS+90] 的出现,以及针对许多大型计算任务的商用计算机集群的兴起。未来的所有数据库系统都必须从头开始设计来运行这些集群。
2.2 内存数据库
鉴于 RAM 容量在过去几十年里的急剧增长,我们有充分的理由相信,很多 OLTP 系统已经或很快将会被放入内存,尤其是大型集群的聚合内存。这在很大程度上归因于大多数 OTLP 系统的尺寸没有像 RAM 容量一样在显著增长,因为它们记录的信息所涉及到的客户、产品和其他现实世界实体的数量并没有按照摩尔定律来增长。鉴于这种情况,数据库厂商创建能够优化内存系统常见用例的系统是有道理的。在这些系统中,考虑优化的索引 [RR99, RR00] 以及避免磁盘优化的元组格式和页面布局(或者缺乏它们) [GS92] 十分重要。
2.3 OLTP 系统中的单线程
所有现代数据库包含对多线程的广泛支持,包括一系列事务并发控制协议以及使用锁存命令广泛渗透它们的代码来支持多线程访问缓冲池和索引页等共享结构。多线程的传统动机在于允许一个事务进行事务处理,同时让另一个事务等待来自磁盘的数据,并防止长时间运行的事务阻碍短时间运行的事务取得进展。
我们断言,所有这些动机都不再有效。首先,如果数据库驻留在内存中,那就不再需要等待来自磁盘数据。此外,生产事务系统不含任何用户等待 —— 事务几乎完全通过存储的程序来执行。其次, OLTP 工作负载十分简单。一个典型的事务由一些索引查找和更新组成,在内存系统中,这些索引查找和更新可以在数百微秒内完成。此外,随着现代数据库行业分叉为一个事务处理和一个数据仓库市场,长期运行(分析)的查询现在由数据仓库提供服务。
我们关心的一个问题就是,多线程需要支持配有多个处理器的机器。然而,我们认为,这个问题的解决方式可以是,把拥有多个处理器的一个物理节点当作一个无共享集群中的多个节点来处理,这可能是由一个虚拟机监视器来进行管理,而这个监视器可以动态地在这些逻辑节点之间分配资源 [BDR97] 。
另一个问题是,网络将会变成新磁盘,从而将延迟引入分布式事务并且需要事务的重新引入。在普通情况下,这个问题无疑是存在的,但对于很多事务应用来说,划分工作负载使其成为 “ 单站点 ”[_ Hel07, SMA+07] 负载是可能的,这样所有的事务可以完全在集群的一个单一节点上运行。
因此,某些类别的数据库应用将不需要支持多线程;在这些数据库系统中,传统的封锁和锁存代码成为不必要的开销。
2.4 高可用性与日志记录
产品事务处理系统需要 24x7 全天候的可用性。为此,大多数系统使用某种形式的高可用性,本质上是使用两倍(或更多倍)的硬件来确保在发生故障时有一个可用的备用品。
最近的论文 [LM06] 指出,至少对于仓库系统来说,利用这些可用的备用品来促进恢复是可能的。特别是,我们可以通过从其他数据库副本复制丢失状态来完成恢复,而不是使用 REDO 日志。在我们之前的研究中,我们已经声称这也可以用于事务系统 [SMA+07] 。如果事实确实如此的话,那么传统数据库中的恢复代码也将成为不必要的开销。
2.5 事务变体
尽管很多 OLTP 系统明确需要事务语义,但最近出现了一些针对具有弱一致性的数据管理系统的方案,特别是在互联网领域。通常,我们相信可用性比事务语义更为重要,因此我们需要的是某种形式的最终一致性 [Bre00, DHJ+07] 。此类环境的数据库可能不太需要针对事务(例如日志、锁、两阶段提交等)开发的机器。
即使有人需要某种严格一致性,也是可能存在很多弱一致性模型的。例如,快照隔离(非事务型)的广泛采用表明,很多用户愿意用事务语义来换取性能(就此例而言,归因于读锁的消除)。
最后,最新的研究表明,数量有限的一些事务形式需要的机器远少于标准数据库事务所需要的机器。例如,如果所有的事务都是 “ 两阶段 ” ,即它们在任何写入操作之前执行它们的所有读取操作,并得到在完成读取之后不会中止的保证,那么 UNDO 日志没有存在的必要 [AMS+07, SMA+07] 。
2.6 总结
如我们的参考文献所示,一些研究小组,包括 _ Amazon [DHJ+07] 、 HP [AMS+07] 、 NYU [WSA97] 和 MIT
[SMA+07] ,已经展示了他们对构建与经典 OTLP 设计之间存在本质区别的系统的兴趣。特别是, MIT H-Store [SMA+07] 系统证明,移除所有上述功能可以在事务吞吐量方面带来两个数量级的加速,这表明其中一些数据库变体很有可能提供卓越的性能。因此,传统的数据库厂商似乎有必要考虑生产明确禁用这些功能的产品。为了帮助这些实践者理解他们可能考虑构建的不同变体的性能影响,我们继续对 Shore 以及我们构建的它的变体进行详细的性能研究。
——待续——
最后
以上就是温柔面包为你收集整理的Michael Stonebraker最新数据库白皮书:窥镜下的OLTP以及我们的发现(一)的全部内容,希望文章能够帮你解决Michael Stonebraker最新数据库白皮书:窥镜下的OLTP以及我们的发现(一)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复