事务(Transaction)是指作为单个逻辑工作单元(Unit)执行的一系列操作,要么完全地执行,要么完全地不执行。事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。
ACID
原子性
事务的原子性是指事务必须是一个原子的操作序列单元。事务中包含的各项操作在一次执行过程中,只允许出现以下两种状态之一。
- 全都成功执行
- 全部不执行
任何一项操作失败都将导致整个事务失败,同时其他已经被执行的操作都将被撤销并回滚,只有所有的操作全部成功,整个事务才算是成功。
一致性
一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。即使事务是并发多个,系统也必须如同串行事务一样操作。其主要特征是保护性和不变性(Preserving an Invariant)。
隔离性
事务的隔离性是指在并发环境中,并发的事务是相互隔离的,一个事务的执行不能被其他事务干扰。也就是说,不同的事务并发操纵相同的数据时,每个事务都有各自完整的数据空间,即一个事务内部的操作及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
在标准SQL规范中,定义了四个事务隔离级别,不同的隔离级别对事务的处理不同,又低到高分别为 Read uncommitted 、Read committed 、Repeatable read 、Serializable 。而且,在事务的并发操作中可能会出现脏读,不可重复读,幻读。
- Read uncommitted
顾名思义,就是一个事务可以读取另一个未提交事务的数据。这个隔离级别允许脏读,隔离级别最低。换句话说,如果一个事务正在处理某一数据,并对其进行了更新,但同时尚未完成事务,即没有进行事务提交。在此同时,允许另一个事务能够访问该数据。比如事务A对起始值为1的i值循环做加1操作,直到i值为10后进行事务提交,此时,事务B能够看到i值在事务A操作过程中的所有中间值(2,3,4等),这些中间值就是数据脏读。 - Read committed
一个事务要等另一个事务提交后才能读取数据。这个隔离级别解决了脏读,以上面的列子,事务B看不到事务A的中间值,只能看到最终的10。另外,如果说有一个事务C,和事务A进行类似的操作,只是事务C是将数据项从10加到20,此时事务B读取到的值是20。这个隔离级别是读取只能读取事务提交后的值,不能读中间值。但是这个隔离状态,会导致一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。 Repeatable read
可重复读,就是在开始读取数据事务开启时,不再允许修改操作。简单来说,就是保证在事务处理过程中,多次读取同一个数据时,其值都和事务开始时刻是一致的。这个隔离级别禁止了不可重复读取和脏读取,但是有可能出现幻读。幻读的是指同样的事务操作,在前后两个时间段内执行对同一个数据项的读取,可能会出现不一致的结果。在上面的例子中,可重复读隔离级别保证了事务B在第一次事务操作过程中,始终对数据项读取到1,但是在下一次事务操作中,即事务B′采用同样的查询方式,就可能读取到10或者20。Serializable
序列化/串行话是最严格的事务隔离级别。它要求所有事务都被串行执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能
事务隔离级别越高,就越能保证数据的完整性和一致性,但同时对并发性能的影响也越大。
持久性
事务的持久性也被称为永久性,是指一个事务一旦提交,它对数据库中对应数据的状态变更就应该是永久性的。换句话说,一旦某个事务成功结束,那么它对数据库所做的更新就必须被永久保存下来——即使发生系统崩溃或机器宕机等故障,只要数据库能够重新启动,那么一定能够将其恢复到事务成功结束时状态。
分布式事务
对于本地事务处理或者是集中式的事务处理系统来说,ACID模型能保证数据的严格一致性,但是对于分布式系统来说,可用性和严格一致性之间出现冲突。因为当我们要求分布式系统具有严格一致性时,每当分布式系统中某个节点有一个数据进行更新后,要更新这个数据的所有副本,而且在更新完成之前,这些数据副本不能被读写,否则会发生脏读。因此,在可用性和一致性之间永远无法存在一个两全其美的方案,对于如何构建一个兼顾可用性和一致性的分布式系统成为了无数工程师探讨的难题,出现了诸如CAP和BASE这样的分布式系统经典理论。
CAP定理
CAP定理:一个分布式系统不可能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三个基本需求,最多只能同时满足其中的两项。
一致性
在分布式环境中,一致性是指数据在多个副本之间是否能够保持一致的特性。在一致性的需求下,当一个系统在数据一致的状态下执行了更新操作后,应保证系统的数据还是处于一致的状态。也就是说,某个节点对一个数据更新后,要保证这份数据在这个系统中所有副本的数据都更新。可用性
可用性是指系统提供的服务必须一直处于可用的状态,对于用户的每个操作请求总是能够在有限的时间内返回结果。
“有限的时间”是指对于用户的每个操作请求,系统必须能够在指定的时间(因场景而改变的合适时间)范围内返回对应的处理结果,如果超过了这个时间范围,那么系统就被认为是不可用的。
“返回结果”是指,对于每个用户请求,都能返回一个正常的响应结果,能够明确地放映出对请求的处理结果,即成功或失败,而不是一个让用户感到困惑的返回结果。分区容错性
分区容错性是指,分布式系统在遇到任何网络分区故障时,仍然能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障。
网络分区是指在分布式系统中,不同的节点分布在不同的子网络中,由于一些特殊的原因导致这些子网络之间出现网络不连通的状况,但各个子网络的内部网络是正常的,从而导致整个系统的网络环境被切分成了若干个孤立的区域。
根据CAP定理中,三者只能选其二,那么
放弃C
这里所说的放弃一致性,并不是完全不需要数据一致性,知识放弃强一致性,保留数据的最终一致性。就是说系统无法保证数据保持实时的一致性,但是能够确保最终会达到一个一致的状态。这就是引入了时间窗口,具体多久能够达到数据一致取决于系统的设计,主要包过数据副本在不同节点之间的复制时间长短。放弃P
如果希望能够避免系统出现分区容错性问题,一种较为简单的做法是将所有数据都放在一个分布式节点上。这样的做法能够隔绝网络分区带来的负面影响,但是也基本放弃了系统的可扩展性。放弃A
相对于放弃P,放弃A则正好相反,其做法是一旦系统遇到网络分区或其他故障时,那么受到影响的服务需要等待一定时间,因此在等待期间系统无法对外提供正常的服务,即不可用。
从CAP定理中可以看出,一个分布式系统不可能同时满足一致性、可用性和分区容错性这三个需求。因为分布式系统的节点必然要被部署到不同的节点,那么必然出现子网络,而网络问题会导致数据一致性的异常情况,因此需要系统架构师在三者中寻求平衡。
BASE理论
BASE理论是Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语的简写。是对CAO中一致性和可用性权衡的结果,其核心思想是即使无法做到强一致性,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。
基本可用
基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性,但这不等价于系统不可用。比如是指响应时间变长,降级处理等。软状态
软状态是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。最终一致性
最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能到达到一个一致的状态。
BASE理论面向的是大型高可用可扩展的分布式系统,和传统事务的ACID特性是相反的,它完全不同于ACID的强一致性模型,而是通过牺牲强一致性来获取可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。