【从零开始学习计算机科学】数据库系统(六)DBMS事务管理
【从零开始学习计算机科学】数据库系统(六)DBMS事务管理
-
- DBMS事务管理
-
- 事务概念
- 事务的特性
- 事务的状态
- 事务的调度
- 事务的隔离
- SQL的四种隔离级别
DBMS事务管理
事务概念
事务是构成单一逻辑工作单元的操作集合。事务是访问并可能更新各种数据项的一个程序执行单元。DBMS通过保证要么执行整个事务,要么一个操作也不执行,达到使数据始终处于一个一致状态。
事务的特性
关系数据库中事务的ACID特性
- 原子性A-特性(Atomicity)
原子性是指事务是一个不可再分割的工作单元,事务中的操作要么都发生,要么都不发生。
在DBMS中,默认情况下一条SQL就是一个单独事务,事务是自动提交的。只有显式的使用start transaction
开启一个事务,才能将一个代码块放在事务中执行。
- 一致性C-特性(Consistency)
一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
如A给B转账,不论转账的事务操作是否成功,其两者的存款总额不变(这是业务逻辑的一致性,至于数据库关系约束的完整性就更好理解了)。
保障机制(也从两方面着手)如下:数据库层面会在一个事务执行之前和之后,数据会符合你设置的约束(唯一约束,外键约束,check约束等)和触发器设置;此外,数据库的内部数据结构(如 B 树索引或双向链表)都必须是正确的。业务的一致性一般由开发人员进行保证,亦可转移至数据库层面。
- 隔离性I-特性(Isolation)
多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果。
在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
事务最复杂问题都是由事务隔离性引起的。完全的隔离性是不现实的,完全的隔离性要求数据库同一时间只执行一条事务,这样会严重影响性能。
- 持久性D-特性(Durability)
这是最好理解的一个特性,持久性,意味着在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。(完成的事务是系统永久的部分,对系统的影响是永久性的,该修改即使出现致命的系统故障也将一直保持)
对于转账、取钱的情境下,其ACID特性可以表述为以下形式:
- 一致性:在这里,一致性要求事务的执行不改变A、B之和。如果没有一致性要求,金额可能会被事务凭空创造或销毁!容易验证,如果数据库在事务执行前是一致的,那么事务执行后数据库仍将保持一致。
- 原子性:假设事务T,执行前账户A和账户B分别有$1000和$2000。现在假设在事务T,执行时系统出现故障,导致T的执行没有成功完成。我们进一步假设故障发生在write(A)操作执行之后write(B)操作执行之前。在这种情况下,数据库中反映出来的是账户A有$950,而账户B有$2000。这次故障导致系统丢失了$50。特别地,我们注意到A + B的和不再维持原状。这样,由于故障,系统的状态不再反映数据库本应描述的现实世界的真实状态。我们把这种状态称为不一致状态( inconsistent state)。我们必须保证这种不一致性在数据库系统中是不可见的。
- 持久性:一旦事务成功地完成执行,并且发起事务的用户已经被告知资金转账已经发生,系统就必须保证任何系统故障都不会引起与这次转账相关的数据丢失。持久性保证一旦事务成功完成,该事务对数据库所做的所有更新就都是持久的,即使事务执行完成后出现系统故障。
- 隔离性:如果几个事务并发地执行,即使每个事务都能确保一致性和原子性,它们的操作会以人们所不希望的某种方式交叉执行,这也会导致不一致的状态。正如我们先前看到的,例如,在A至B转账事务执行过程中,当A中总金额已减去转账额并已写回A,而B中总金额加上转账额后还未写回B时,数据库暂时是不一致的。如果另一个并发运行的事务在这个中间时刻读取A和B的值并计算A + B,它将会得到不一致的值。尽管多个事务可能并发执行,但系统保证,每个事务都感觉不到系统中有其他事务在并发地执行。
事务的状态
正如我们先前所注意到的,事务并非总能成功地执行完成。这种事务称为中止(aborted)了。我们如果要确保原子性,中止事务必须对数据库的状态不造成影响。因此,中止事务对数据库所做过的任何改变必须撤销。一旦中止事务造成的变更被撤销,我们就说事务已回滚(rolled back)。恢复机成功完成执行的事务称为已提交(committed)。一个对数据库进行过更新的已提交事务使数据库进入一个新的一致状态,即使出现系统故障,这个状态也必须保持。
我们需要更准确地定义一个事务成功完成的含义。为此我们建立了一个简单的抽象事务模型。事务必须处于以下状态之一。
- 活动的( active ):初始状态,事务执行时处于这个状态。
- 部分提交的( partially committed ):最后一条语句执行后。
- 失败的( failed ):发现正常的执行不能继续后。
- 中止的( aborted ):事务回滚并且数据库已恢复到事务开始执行前的状态后。
- 提交的( committed ):成功完成后。
事务相应的状态图如下图所示。只有在事务已进入提交状态后,我们才说事务已提交。类似地,仅当事务已进入中止状态,我们才说事务已中止。如果事务是提交的或中止的,它称为已经结束的(terminated)。
事务状态图
事务状态图作用是便于系统跟踪各事务执行情况;保证事务原子性和持久性特点。
事务的调度
调度:一组指令包括指令在系统中执行的特定时间顺序。(指令可能来自多个事务),包括commit,abort指令。
- 串行调度:调度中凡属于同一个事务的指令都紧挨着一起。即一个事务的指令都执行完成后在执行下一事务。其虽保证执行结果正确,但应用并发执行度差。
- 并行调度:调度中多个事务的指令在时间上相互交叉地在执行。虽应用并发执行度高,但执行结果可能错误。
- 可串行化调度:虽然可能是一个并行调度,但在执行的效果上等同于某一个串行调度执行结果。其应用并发执行度较高,且执行结果依然正确。
这里的并行调度是指宏观上的并行,与多进程单核CPU类似,系统在某一时间内只能执行一条指令,但是其可以交替执行不同事务的不同指令,导致其从宏观上来看是多个事务在同时执行。
- 冲突可串行化
指令的顺序
考虑一个调度S中的两条连续指令(仅限于read与write操作) I i I_i Ii与 I j I_j Ij,分别属于事务 T i T_i Ti与 T j T_j Tj,有以下四种可能情况:
- I i I_i Ii = re