数据库事务的ACID(原子性,一致性,隔离性,持久性)四大特性
我从维基百科翻译的。翻译水平有限:
在计算机科学中,ACID(原子性,一致性,隔离性,持久性)是数据库事务的一组属性,旨在即使在发生错误,断电等情况下也可以确保有效性。在数据库的上下文中,这是指一系列数据库操作,它们可以满足ACID属性(并且可以将这些属性视为对数据的单个逻辑操作)称为事务。例如,从一个银行帐户到另一个银行帐户的资金转移,即使涉及多个更改,例如从一个帐户借记而向另一个帐户贷记,也只是一次交易。
1983年, Andreas Reuter和TheoHärder在吉姆·格雷(Jim Gray)提出原子性,一致性和持久性的早期工作的基础上,加了个隔离性。将首字母缩写ACID称为原子性,一致性,隔离性和持久性的简写。
Reuter和Härder定义的这四个属性的特征如下:
原子性:
事务通常由多个语句组成。原子性保证将每个事务视为一个单独的“单元”,它要么完全成功,要么完全失败:如果构成事务的任何语句未能完成,则整个事务都会失败,并且数据库将保持不变。原子系统必须保证在每种情况下的原子性,包括电源故障,错误和崩溃。原子性的保证可以防止仅部分更新数据库,这可能比直接拒绝整个事务的系列操作引起更大的问题。原子事务的一个示例是从银行帐户A到帐户B的货币转移。它包括两个操作,从帐户A取款并将其保存到帐户B。在原子事务中执行这些操作可确保数据库保留在一个一致的状态,也就是说,如果这两个操作中的任何一个失败,那么钱必须保证不会丢失也不会无端多出来。
一致性:
一致性确保事务只能将数据库从一种有效状态带到另一种状态,并保持数据库不变性:写入数据库的任何数据必须根据所有定义的规则(包括约束,级联,触发器及其任何组合)有效。这可以防止数据库因非法交易而损坏,但不能保证交易正确,因为数据通常是代码写入的,代码计算出错,写进去也是错的,所以一致性并不是用来保证交易正确。这个概念可以参照数据库的完整性保证了主键-外键关系,类似这种意思。
隔离性:
交易通常是同时执行的(例如,多个交易同时读取和写入一个表)。隔离确保并发执行事务使数据库保持与顺序执行事务时所获得的状态相同的状态。隔离是数据库设计开发中并发控制所要实现的目标。根据所使用的方法(有隔离级别),未完成的事务甚至可能对其他事务是不可见。
持久性:
持久性保证了一旦事务被提交,即使在系统故障(例如,停电或崩溃)的情况下,事务也将保持提交。这通常意味着完成的事务(或其影响)被记录在非易失性存储器中。这个比较好理解。
下面是一个案例:
以下示例进一步说明了ACID属性。在这些示例中,数据库表具有两列,即A和B。完整性约束要求A中的值和B中的值之和必须为100。下面的SQL代码如上所述创建一个表:
CREATE TABLE acidtest (A INTEGER, B INTEGER, CHECK (A + B = 100));
然后具体问题具体分析:
原子性:原子性保证了原子事务中的一系列数据库操作要么全部发生(成功的操作),要么都不发生(不成功的操作)。无法仅执行其中一部分操作就将一系列操作分开,这使得该系列操作“不可分割”。原子性的保证可以防止仅部分更新数据库,这可能比直接拒绝整个事务一系列操作引起更大的问题。换句话说,原子性意味着不可分割性和不可还原性。或者,我们可以说逻辑事务可以由一个或多个物理事务组成。除非执行了所有物理事务,否则逻辑事务不会发生对数据库的影响。假设我们的逻辑交易为将资金从帐户A转移到帐户B。此逻辑交易可能由几笔物理交易组成,这些交易包括首先从帐户A中删除这笔金额作为第一笔物理交易,然后作为第二笔物理交易将所述金额转入帐户B。然后,除非两次物理交易都发生且该金额已转移到帐户B中,否则转帐不会对数据库产生影响。
一致性:一致性是一个非常笼统的术语,它要求数据必须符合所有验证规则。在前面的示例中,验证是A + B = 100的要求。必须检查所有验证规则以确保一致性。假定事务尝试从A减去10而未更改B。由于在每次事务之后都会检查一致性,因此已知在事务开始之前A + B = 100。如果一个事务成功从A中删除10,将实现原子性。但是,验证检查将显示A + B = 90,这与数据库规则不一致,就会取消整个事务,并将受影响的行回滚到其事务前的状态。如果存在其他约束,触发器或级联,则在提交事务之前,将以与上述相同的方式检查每个更改操作。其他约束条件可能会出现类似的问题。我们可能要求A和B的数据类型均为整数,例如,如果我们输入A的值13.5,则交易将被取消,或者系统可能以触发器的形式发出警报(如果/已将触发器写入此效果)。另一个例子是完整性约束,它不允许我们删除一个表中的行,该行的主键被其他表中的至少一个外键引用,这个时候也是违反了事务的一致性,因为破坏了验证规则。
隔离性:为了证明隔离,我们假设两个事务同时执行,每个事务都试图修改相同的数据。两者之一必须等到另一个完成才能保持隔离。 考虑两个事务:T1从A到B转移10。T2从B到A转移20。
有四个动作:
(1)T1从A减去10。
(2)T1将B加10。
(3)T2从B减去20。
(4)T2将A加20。
如果按顺序执行这些操作,则尽管T2必须等待,但仍可保持隔离。考虑如果T1中途失败,会发生什么情况。该数据库消除了T1的影响,而T2还是会看到有效数据。
通过对事务进行交织,操作的实际顺序可能是:
(1)T1从A减去10。
(2)T2从B减去20。
(3)T2将A加20。
(4)T1将B加10。
考虑如果在步骤4中修改B时T1失败,相当于T1未提交,但是T2读了T1未提交的数据,会发生什么情况。 如果不离开无效的数据库,则无法将其还原到T1之前的值。 这被称为写-写失败,因为两个事务试图写入同一数据字段。在系统中,可以通过恢复到最后一个已知的良好状态,回滚失败的事务T1,并重新启动事务T2来解决问题。
持久性:考虑一个将10从A转移到B的事务。首先它从A删除10,然后将10加到B。这时,用户被告知该交易成功。 但是,更改仍在磁盘缓冲区中排队,等待提交到磁盘。 电源故障,更改丢失。 但是只要事务提交就是有效的。