事务特性

事务

在数据系统的残酷现实中,很多事情都可能出错:

  • 数据库软件、硬件可能在任意时刻发生故障(包括写操作进行到一半时)。
  • 应用程序可能在任意时刻崩溃(包括一系列操作的中间)。
  • 网络中断可能会意外切断数据库与应用的连接,或数据库之间的连接。
  • 多个客户端可能会同时写入数据库,覆盖彼此的更改。
  • 客户端可能读取到无意义的数据,因为数据只更新了一部分。
  • 客户之间的竞争条件可能导致令人惊讶的错误。

为了实现可靠性,系统必须处理这些故障,确保它们不会导致整个系统的灾难性故障。但是实现容错机制工作量巨大。需要仔细考虑所有可能出错的事情,并进行大量的测试,以确保解决方案真正管用。数十年来,事务(transaction)一直是简化这些问题的首选机制,事务是一个抽象层,允许应用程序假装某些并发问题和某些类型的硬件和软件故障不存在;各式各样的错误被简化为一种简单情况:事务中止(transaction abort),而应用需要的仅仅是重试。事务是应用程序将多个读写操作组合成一个逻辑单元的一种方式。从概念上讲,事务中的所有读写操作被视作单个操作来执行:整个事务要么成功提交(commit)要么失败中止(abort)或回滚(rollback)。如果失败,应用程序可以安全地重试。对于事务来说,应用程序的错误处理变得简单多了,因为它不用再担心部分失败的情况了,即某些操作成功,某些失败(无论出于何种原因)。

事务是为了简化应用编程模型而创建的。通过使用事务,应用程序可以自由地忽略某些潜在的错误情况和并发问题,因为数据库会替应用处理好这些,我们称之为安全保证(safety guarantees)。并不是所有的应用都需要事务,有时候弱化事务保证、或完全放弃事务也是有好处的(例如,为了获得更高性能或更高可用性)。一些安全属性也可以在没有事务的情况下实现。

事务的起源

现今,几乎所有的关系型数据库和一些非关系数据库都支持事务。其中大多数遵循 IBM System R(第一个 SQL 数据库)在 1975 年引入的风格。40 年里,尽管一些实现细节发生了变化,但总体思路大同小异:MySQL,PostgreSQL,Oracle,SQL Server 等数据库中的事务支持与 System R 异乎寻常地相似。

2000 年以后,非关系(NoSQL)数据库开始普及。它们的目标是通过提供新的数据模型选择,并通过默认包含复制和分区来改善关系现状。事务是这种运动的主要原因:这些新一代数据库中的许多数据库完全放弃了事务,或者重新定义了这个词,描述比以前理解所更弱的一套保证。随着这种新型分布式数据库的炒作,人们普遍认为事务是可扩展性的对立面,任何大型系统都必须放弃事务以保持良好的性能和高可用性。另一方面,数据库厂商有时将事务保证作为“重要应用”和“有价值数据”的基本要求。这两种观点都是纯粹的夸张。