事务属性

2024年12月8日 | 7 分钟阅读

从事务的定义可以清楚地看出,单个事务可能包含一系列在数据库内部执行的操作。一旦事务被提交,它应该执行所有属于它的操作,并在最终完成时,通知用户成功或失败以及事务对数据库所做的更改。

当多个用户并发地(即同时)提交事务时,由于事务的重叠,数据库可能会出现不一致的状态。因此,为了在并发访问和系统故障的情况下实现数据完整性,事务应该具有原子性、一致性、隔离性和持久性。这些属性被称为ACID属性,取自每个属性的首字母。

什么是事务?

事务是构成单个逻辑工作单元的一系列操作的集合。事务有四个属性。这些属性用于在事务执行前后维护数据库的一致性。构成事务的各种操作通常包括添加新数据、修改现有数据、访问现有数据或这些操作的组合。ACID属性如下:

事务的属性

  1. 原子性
  2. 一致性
  3. 隔离
  4. 耐用性
DBMS Transaction property

原子性

  • ○ “全有或全无”这个短语描述了第一个ACID属性,即原子性。
  • 它规定事务的所有操作要么全部发生,要么事务被中止。
  • 没有中间状态,即事务不能部分发生。每个事务都被视为一个单元,要么运行到完成,要么根本不执行。

原子性属性的特点

  • 要么事务中的所有操作都完成,要么一个都不完成。
  • 在磁盘、CPU、数据库软件和应用软件发生故障时,原子性仍然得到维护。
  • 在出现死锁的情况下,原子性仍然得到维护。
  • 它可以在系统级别和会话级别上被锁定。
  • 确保原子性是数据库系统自身的责任。

原子性涉及以下两个操作:

中止(Abort): 如果一个事务中止,那么它所做的所有更改都不可见。

提交(Commit): 如果一个事务提交,那么它所做的所有更改都可见。

示例: 让我们假设有以下事务T,由T1和T2组成。A账户有600元,B账户有300元。将100元从A账户转到B账户。

T1T2
读取(A)
A := A - 100
写入(A)
读取(B)
Y := Y + 100
写入(B)

事务完成后,A账户有500元,B账户有400元。

如果事务T在完成事务T1之后但在完成事务T2之前失败,那么金额将从A账户扣除,但不会添加到B账户。这显示了数据库的不一致状态。为了确保数据库状态的正确性,事务必须被完整地执行。

维护原子性的机制是由DBMS完成的,它会跟踪执行写入操作的数据的旧值,如果事务没有完成其执行,旧值将被恢复,就好像该事务从未被执行过一样。

一致性

  • “不违反完整性约束”这个短语描述了一致性属性。
  • 完整性约束被维护,以使数据库在事务执行前后保持一致。
  • 事务的执行将使数据库处于其先前的稳定状态或一个新的稳定状态。
  • 数据库的一致性属性指出,每个事务都看到一个一致的数据库实例。
  • 事务用于将数据库从一个一致状态转换到另一个一致状态。

例如: 总金额必须在事务前后保持不变。

因此,数据库是一致的。在T1完成但T2失败的情况下,就会出现不一致。

没有一致性属性,事务可能会错误地贷记或借记资金。编写事务代码的应用程序员有责任通过在数据库上强制执行一致性约束来为单个事务维护一致性。

隔离

  • 它表明,在一个事务执行期间使用的数据不能被第二个事务使用,直到第一个事务完成。
  • 在隔离性中,如果事务T1正在执行并使用数据项X,那么该数据项不能被任何其他事务T2访问,直到事务T1结束。
  • DBMS的并发控制子系统强制执行隔离性属性。

实现隔离性

当多个事务并发执行时,即使每个事务都满足原子性和一致性属性,也可能出现问题。这些问题是由于并发运行的事务重叠造成的,即当事务相互干扰时。

示例: 现在让我们考虑两个并发执行的事务T1和T2。事务T1从账户A向账户B转账750元,事务T2从账户A向账户B转账20%的金额。假设最初账户A和B的余额分别为5000元和8000元。

现在,事务T1和T2并发运行的调度如下图所示

调度1:一致状态

T1T2描述/状态
读取 (A)
A := A – 750
写入 (A)
5000元
4250元
存储到A
读取 (A)
temp := A * 0.2
A := A – temp
写入 (A)
4250元
850元
3400元
存储在A中
读取 (B)
B := B + 750
写入 (B)
8000元
8750元
存储到B
读取 (B)
B := B + temp
写入 (B)
8750元
9600元
存储在B中

调度2:不一致状态

T1T2描述/状态
读取 (A)
A := A – 750
5000元
4250元
读取 (A)
temp := A * 0.2
A := A – temp
写入 (A)
读取 (B)
5000元
1000元
4000元
存储到 A = 4000
8000元
写入 (A)
读取 (B)
B := B + 750
写入 (B)
存储到 A = 4250
8000元
8750元
存储到 B = 8750
B := B + temp
写入 (B)
9600元
存储到 B = 9000

调度1导致了数据库的一致状态,因为它显示了在事务执行前后,账户A和B的总和为13000元。

现在考虑调度2,其中事务T1对账户A执行了写操作,将其值更新为4250元,即从账户A减少了750元。在此期间,另一个事务T2读取了账户A的余额,即5000元。

现在它计算账户A金额的20%,并将其存储在临时变量temp中。然后,它通过从账户A的初始余额5000元中扣除临时变量的值1000元,将账户A的余额更新为4000元。现在它也读取了账户B的余额。在进一步执行之前,事务T1获得控制权并对账户A执行写操作。现在事务T1和账户B中的余额值,因此它将B的值更新为9000元,而不是9750元。因此,账户A和B的总和变为13250元 = (4250 + 9000),这导致了不一致,因为它应该是13000元。

解决上述问题的一种可能方法是串行执行上述事务,即一个接一个地执行。但这也可能导致问题。假设一个长事务首先被执行,那么所有其他事务都必须在队列中等待,即使某些事务彼此不干扰。因此,对于这样的事务,没有必要在队列中等待。

然而,并发执行一组事务可以提供性能上的好处。因此,DBMS已经开发了其他解决方案,允许在没有任何问题的情况下并发执行多个事务。调度1中解释了一种可能的方法。这是隔离性属性的要求,它要求在一个事务执行期间使用的数据不能被第二个事务使用,直到第一个事务完成。隔离性属性由DBMS的并发控制组件处理。

耐用性

  • 持久性属性用于指示数据库一致状态的性能。它规定事务的更改是永久性的。
  • 它们不会因为错误事务的误操作或系统故障而丢失。当一个事务完成时,数据库达到一个称为一致状态的状态。即使在系统发生故障的情况下,该一致状态也不会丢失。
  • DBMS的恢复子系统负责持久性属性。

DBMS维护一个称为日志的记录,它跟踪对数据库的所有写入操作。日志有助于确保持久性。如果系统在已完成的事务所做的更改写入磁盘之前崩溃,当系统重新启动时,日志将用于记住这些更改。


下一主题DBMS 事务状态