Design Data-Intensive Applications 读书笔记十八 第七章:事务,ACID

事务 Transaction

在实际使用中,很多事情会出错:

1、数据库软件可能在任何时候出错(包括写入过程中)。

2、应用可能在任何时候故障(包括在一些列操作过程中)。

3、网络问题会终端应用和数据库,或者是数据库节点间的连接。

4、多个客户端可能同时写入数据库,会互相覆盖写入值。

5、客户端可能读取到无意义的数据,因为那是部分更新的值。

6、客户端间的竞态条件可能会造成很多意外的bug。

为了可靠性,需要构建一个能容纳故障的系统。但是实现故障容忍机制需要很多工作。需要仔细考虑任何可能出错的事情,需要很多测试来确保方法一定有效。

几十年来,事务就是其中的一个用于简化问题的机制。事务就是应用将数个读写打包成一个逻辑单元的方法。理论上,一个事务中的所有读写都按一种方式执行:要么整个事务成功,要么整个失败。使用事务,因为不需要担心中间错误,应用可以容易的处理错误。

如果你使用了很多年的事务,可能事务看起来很平常,但是我们不应该将事务看成理所当然。事务并不是自然法则;它们因为特定目标而被设计出来,即用于简化应用连接数据库的编程模型。使用事务,应用可以忽略特定的有潜在问题的场景和并发问题,因为数据库自己处理了这些问题(称之为安全保障)。

不是所有的应用都需要事务,一些时候减弱事务保障或者抛弃事务有好处(比如为了更高的性能或者可用性)。不用事务也可以达成一些安全特性。

那么怎么知道自己是否需要事务?为了回答这个问题,我们需要理解事务提供了什么安全保障,背后的代价是什么。这一章,我们会检查很多出错的例子以及数据库应对错误的算法。我们很深入到并发控制,讨论不同的竞态条件和数据库如何实现不同的隔离等级,如:写入承诺,快照隔离和可串行性 read committed, snapshot isolation, 和serializability

事务的粗略的概念

绝大部分关系型数据库和非关系型数据库都支持事务。大部分都遵循1975年IBM System R,第一个SQL数据库提出的概念。尽管实现细节有差别,但是基本的概念40年来都没变。自2000年以来,非关系数据库开始流行。它们的目的是在关系模型之外提供一个新的数据模型,包括备份和分区特性。事务就是它们的主要动机:很多新一代数据库抛弃了事务,或者是将其重新定义,削弱了它的保证性。

概览新的分布式数据库,事务站在扩展性的对立面这几乎成为共识,另外任务大规模系统都抛弃了事务来获得高性能和高可用。另一方面,传统的事务被数据库供应商描述为“庄重的系统”和“有价值数据”所必须的。这两个观点都过于夸大了。

真相没有那么简单,就像其他技术,事务有优缺点。为了理解背后的取舍,我们来深入探讨事务提供的保障的细节。

ACID的意义

事务提供的安全保障一般描述为ACID, Atomicity, Consistency, Isolation, Durability。但是实际上,一个数据库实现的ACID特性并不等价于其它数据的实现的特性。例如:关于隔离性有很多暧昧不清的地方。想法都是相似的,但是细节里有魔鬼。今天,一个系统声明满足ACID特性,可能并不能提供想象中的保障。ACID很不幸地成为了一个营销术语。

不满足ACID的系统有时候称为BASE, Basically Available, Soft state,和 Eventual consistency,基本可用,软件状态,最终一致。这比ACID更加模糊。一个比较明晰的定义就是BASE是非ACID。

原子性 Atomicity

“原子”一般指代不可再分的最小粒子。计算机中指代类似的概念。例如:在多线程系统中,一个线程执行原子操作,则其他线程没有任何方法看到操作执行的中间状态。系统只可能处于操作前和操作后两个状态。

作为比较,在ACID的概念中,原子性与并发无关,因为隔离性包含了并发概念。原子性是描述如果客户端执行多个写入,写入过程中发生了错误要怎么处理。例如:进程故障,网络断开,磁盘满了或者是违反了完整性约束。如果写入时将写入打包发送至原子性事务,事务因为故障无法完成,那么事务就要被中止,数据库必须丢弃事务之前所做的任何写入。

没有事务性,如果过程中一个错误做了多个改变,系统很难知道做了哪些改动。应用或许可以重试,但是做出两次相同的改动有风险,错误可能会再次发生,也可能导致冗余和错误数据。原子性简化了这个问题:如果事务被中止了,应用可以确定没有任何改动,可以放心地重试。

在发生错误时中止事务并丢弃事务的所有写入的能力,即是原子性。

一致性 Consistency

ACID中的一致性表示你确定你的数据(常量)是正确的,例如,在一个账目系统中,账户的信用和借债应该永远都是平衡的。如果一个事务开始时,依据一些常量,数据库是有效的,事务中的任何写入都维持了有效性,那么你可以确定一直都维持了有效性。

但是,一致性依赖于应用对常量的概念以及应用有责任维护一致性。如果你往数据库中写入错误数据破坏了一致性,数据库无法阻止你。

原子性,隔离性,持久性是数据库的特性,但是一致性是应用的特性。应用可能依赖数据库的原子性和隔离性实现一致性,但是这不是由数据库单独决定的,因此一致性并不真正属于ACID。

隔离性 Isolation

数据库允许多个客户端同时访问。如果它们读写数据库的不同部分,那么不会有问题,如果它们要访问相同的记录,就会遇到并发问题(竞态条件)。

图7-1是这类问题的简单例子。假设你有两个客户端同时更新一个数字。每个客户端需要读取一个当前值,然后加1,最后写入到数据库(假设数据库没有内置的增长操作)。在图7-1中,计数应该从42增长至44,但是两次增长操作发生后,它实际上因为竞态条件只是增长到了43.

ACID中的隔离性意味着同时执行的事务相互隔离:它们不会互相影响。经典的数据库课本将隔离性称为有序性(serializability),意味着每个事务可以伪装成数据库只有这一个事务在执行。数据库确保所有事务提交后,得到的结果与事务有序执行的结果相同,即便实际上它们可能是并发执行的。

但是实际上,有序性隔离很少使用,因为它带来了性能惩罚。一些数据库根本没有实现它,如Oracle 11g,它实际上实现了“快照隔离”,比有序性提供的保障性弱。

持久性 Durability

数据库系统的目的就是提供安全存放数据的地方而不需要担心丢失。持久性就是事务提交成功后,所有写入的数据都不会被遗忘,即便是硬件故障或者是数据库故障。

在单节点数据库中,持久性意味着数据被写入到不易挥发的存储中(硬盘)。它经常包含提前写入日志或者类似的结构(能在数据损坏后恢复数据)。在分布式数据库中,持久性意味着数据已经成功备份至其他节点。为了提供持久性保证,数据库必须等待写入或者备份都完成后在返回事务成功信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值