ACID+CAP+BASE+Transaction(事务)

Posted Data+Science+Insight

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACID+CAP+BASE+Transaction(事务)相关的知识,希望对你有一定的参考价值。

ACID+CAP+BASE+Transaction(事务)

 

See the source image

数据库管理系统中事务(transaction)的四个特性(分析时根据首字母缩写依次解释):原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。(执行单个逻辑功能的一组指令或操作称为事务)。

 

CAP是一致性(Consistency),可用性(Availability),分区容错性(Partition tolerance)的缩写。在分布式系统设计中,任何一个系统都不可能同时满足这三个特性,只能满足其中2个特性。既然是分布式系统,所以分区容错性是必须要有的,所以在实际设计过程中,更多的是在一致性和可用性之间寻找平衡。

 

BASE是Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)的简写。BASE是对CAP中一致性和可用性权衡的结果,契合性思想是即使无法做到强一致性,但每个应用都可以根据自身的业务特点,采用适当的方式来使得系统达到最终一致性。

先介绍什么是脏读,不可重复读,幻读

 

脏读: (读取了未提交的新事物,然后被回滚了)

    事务A读取了事务B中尚未提交的数据。如果事务B回滚,则A读取使用了错误的数据。

    比如我给你转了100万,但是我还没有提交,此时你查询自己账户,多了100万,很开心。然后我发现转错人了,回滚了事物。然后你100万就没了。  在过程中你查到了没有提交事物的数据(多出的100万),这就是脏读。

(解决:如果 一个事物在读的时候,禁止读取未提交的事物。是不是就解决了。)

 

不可重复读: (读取了提交的新事物,指更新操作)

      不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。

  不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。

  在某些情况下,不可重复读并不是问题,比如我们多次查询某个数据当然以最后查询得到的结果为主。但在另一些情况下就有可能发生问题,例如同一个事物前后两次查询同一个数据,期望两次读的内容是一样的,但是因为读的过程中,因为令一个数据写了该数据,导致不可重复读。

(解决:如果 一个事物在读的时候,禁止任何事物写。是不是就解决了。)

 

幻读:(也是读取了提交的新事物,指增删操作)

    在事务A多次读取过程中,事务B对数据进行了新增操作,导致事务A多次读取的数据不一致。幻读和不可重复读的区别在于,不可重复是针对记录的update操作,只要在记录上加写锁,就可避免;幻读是对记录的insert操作,要禁止幻读必须加上全局的写锁(比如在表上加写锁)。

(解决,如果一个事物加上表级锁,只要有任何东西操作这个表的时候,禁止任何操作的并发)

 

另外说一下两类丢失更新:

 

第一类事物丢失:(称为回滚丢失) 

     对于第一类事物丢失,就是比如A和B同时在执行一个数据,然后B事物已经提交了,然后A事物回滚了,这样B事物的操作就因A事物回滚而丢失了。

        举个例子,比如我又1000元。买一个东西,花了100元。然后我朋友给我转了1000元。理论上这两个事物正常的话,我应该还有1900元。  

        但是比如现在两个A,B事物同时进行,第一步都先查询我余额还有1000元,然后B事物给我转了1000元,提交了,理论上我还有2000元。然后我买东西,100元的,买到一半,我事物回滚,就回滚成了1000元。(回滚丢失)如果我不回滚,也提交了,我就还剩900元(也就是下面介绍的第二类事物丢失,覆盖丢失)。

 

第二类事物丢失:(提交覆盖丢失)

    对于第二类事物丢失,也称为覆盖丢失,就是A和B一起执行一个数据,两个同时取到一个数据,然后B事物首先提交,但是A事物加下来又提交,这样就覆盖了B事物,称为第二类事物丢失,覆盖丢失。

 

对上面 脏读,不可重复读 ,幻读 , 第一类事物丢失(回滚丢失) ,第二类事物丢失(覆盖丢失) 有什么预防方法呢?

接下来讲事物的4个隔离级别:

从低到高开始:

 

1. 原子性

原子性是指事务是一个不可再分割的工作单元,事务中的操作要么都发生,要么都不发生。

可采用“A向B转账”这个例子来说明解释

在DBMS中,默认情况下一条SQL就是一个单独事务,事务是自动提交的。只有显式的使用start transaction开启一个事务,才能将一个代码块放在事务中执行。

2. 一致性

一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。

如A给B转账,不论转账的事务操作是否成功,其两者的存款总额不变(这是业务逻辑的一致性,至于数据库关系约束的完整性就更好理解了)。

保障机制(也从两方面着手):数据库层面会在一个事务执行之前和之后,数据会符合你设置的约束(唯一约束,外键约束,check约束等)和触发器设置;此外,数据库的内部数据结构(如 B 树索引或双向链表)都必须是正确的。业务的一致性一般由开发人员进行保证,亦可转移至数据库层面。

3. 隔离性

多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果。

在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。

事务最复杂问题都是由事务隔离性引起的。完全的隔离性是不现实的,完全的隔离性要求数据库同一时间只执行一条事务,这样会严重影响性能。

关于隔离性中的事务隔离等级(事务之间影响),参见相应博文

4. 持久性

这是最好理解的一个特性:持久性,意味着在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。(完成的事务是系统永久的部分,对系统的影响是永久性的,该修改即使出现致命的系统故障也将一直保持)

write ahead logging:SQL Server中使用了WAL(Write-Ahead Logging)技术来保证事务日志的ACID特性,在数据写入到数据库之前,先写入到日志,再将日志记录变更到存储器中。

 

事务的隔离性,说的就是,多个并发事务实际上都是独立事务上下文,多个事务上下文之间彼此隔离,互不干扰。但是多个事务如果对共享数据进行查看,删除,修改如果不加以修改,就会出现线程安全问题。如何避免,你可能会使用一把锁,当线程A修改共享数据的时候,让线程B不要来查看共享数据,除非等我修改完毕;或者说,我不让别人读取到我修改共享数据的中间值,只能读取到初始值,和我修改完成之后的值。但是这些都是你根据业务来操作的,所以数据库为我们封装了‘四把锁’,对应四种隔离级别:

 

读未提交(Read Uncommitted),其隔离级别最低,允许脏读。换句话说就是,如果一个事务正在处理某一数据,并对其进行了更新,但是同时没有提交事务,允许另一个事务也可以访问。写加锁,读不加锁)写操作加写锁,读操作不加锁。禁止第一类丢失更新,但是会出现所有其他数据并发问题。

 

读已提交(Read Committed),和读未提交的区别就是。读未提交可以读取到别人没有提交的数据,但是读已提交只能读取到别人提交后的值,事务进行的中间值不会读取到。(写加锁,读加锁)写操作加写锁,读操作加读锁。禁止第一类丢失更新和脏读。就是你已经开始读了数据,然后一个事物开始写,然后写的事物不提交的话,是不能进行读的事物,避免了脏读。

 

可重复读(Repeatable Read),简单来说就是事务处理过程中多次读取同一个数据的时候,这个值不会发生改变,其值都和第一次查询到的数据是一致的。

(写加锁,读加锁)对于读操作加读锁到事务结束,其他事务的更新操作只能等到事务结束之后进行。

和提交读的区别在于,提交读的读操作是加读锁到本次读操作结束,可重复读的锁粒度更大。禁止两类丢失更新,禁止脏读和不可重复度,但是可能出现幻读。

一个事务读的时候,我们把两次读看成整体,在读的过程中,不允许写的操作,这样就可以实现重复读。就是两次读操作不允许其他事务。

这是大部分关系数据库的默认 隔离级别。

 

串行化(Serializable),是最严格的隔离级别,他要求所有的事务都被串行执行,既事务只能一个接一个的进行处理,不能并发执行。(对表级读 写加锁)

读操作加表级读锁至事务结束。可以禁止幻读。

 

分布式系统都是基于CAP/BASE理论进行设计的。CAP/BASE在分布式系统设计过程中提供了最基本的也是最重要的原则。

正确的理解CAP/BASE能够更好的指导分布式系统的设计,当然了只有经历了大量的分布式系统实战,才能更加深刻的理解CAP/BASE理论。

 

CAP

CAP是一致性(Consistency),可用性(Availability),分区容错性(Partition tolerance)的缩写。在分布式系统设计中,任何一个系统都不可能同时满足这三个特性,只能满足其中2个特性。既然是分布式系统,所以分区容错性是必须要有的,所以在实际设计过程中,更多的是在一致性和可用性之间寻找平衡。

 

CAP三个特性的具体含义如下:

 

2.1. 一致性:这里说的一致性是指强一致性。分布式系统中,数据都是以多副本的形式存储在不同的节点中,要任何时刻数据副本之间的状态保持一致性。即一个进程对一个节点中的数据进行了更新后,同时其他节点中的数据副本实时也进行了更新。另一个进程读取其他节点的数据是最新版本。

2.2. 可用性:是指在任何时刻系统提供的服务都是可用的。用户或者客户端发送一个请求,服务总是在规定的时间内返回请求结果。在规定的时间内,没有返回请求结果,则认为服务不可用。

2.3. 分区容错性:系统在任何时刻发生网络故障,系统宕机,整个系统仍然能够对外提供可用性服务和一致性服务。这也说明了,在分布式系统设计过程中,更多的是考虑可用性和一致性平衡。

 

BASE理论

 

BASE理论是ebay架构师提出的。主要是指基本可用(Basically Available),软状态(soft state)和最终一致性(Eventually consistent)三个词的缩写。核心思想是即使无法做到强一致性,但是每个应用都可以根据自身业务特点,采用合适的方式达到最终一致性。

Base理论是依据大型的分布式系统架构设计设计经验得来,是一致性和可用性平衡结果。同时,也可以反映出在分布式系统设计中,主要考虑到PA两个特性,最终实现数据一致性。

 

BASE理论三个要素:

 

3.1. 基本可用:基本可用是指允许发生不可预知的故障,但是服务对外照常可用。只是损失部分可用性。

3.2. 弱状态 :数据副本在整个服务运行期间,允许在某一个时刻(比如,数据复制)允许存在中间状态,但是最终数据的状态保持一致。在处于弱状态时,整个服务可用。

3.3 最终一致性:在经过一定的时间后,所有数据副本的状态都已经保持一致。一致性的本质就是要保证数据最终一致性。

 

小结:

Base/CAP理论,在分布式系统建设中提供了一个大的原则和方向。具体的设计过程中,还需要根据不同的系统的业务特点,灵活去设计,考虑的侧重点不同。

 

参考:数据库ACID四大特性及脏读,不可重复读,幻读,事物丢失

参考:简述从ACID到CAP/BASE

参考:CAP和BASE理论理解

参考:数据库的ACID(原子性、一致性、隔离性与持久性)

参考:数据库事务的四大特性(ACID)以及事务的隔离级别

 

 

以上是关于ACID+CAP+BASE+Transaction(事务)的主要内容,如果未能解决你的问题,请参考以下文章

谈谈ACID以及CAP/BASE理论

CAP向左,CAP向右,ACID和BASE理论

关于ACID理论和CAP理论

关于ACID理论和CAP理论

关于ACID理论和CAP理论

CAP BASE ACID