事务的原子性和持久性

  • 如何精确地描述成功完成执行的事务?
  • 事务的整个执行过程是怎样的?
  • 事务的原子性和持久性是如何实现的?

精确描述事务

基本思想:通过有限状态机
一个事务必定处于以下的状态之一:

  • 激活状态
  • 部分已提交状态
  • 已失败状态
  • 已终止状态
  • 已提交状态
事务的原子性和持久性_第1张图片
事务状态转换图.png

事务概念定义

  • 什么是已提交的事务?
    事务进入了已提交状态
  • 什么是已中止的事务?
    事务进入了已中止的状态
  • 什么是已终止的事务?
    进入已提交或者已中止的事务

已提交的事务

已提交的事务是一个成功完成执行的事务。
已执行更新且已提交的事务将数据库转换到一种新的一致性状态,即使发生了故障,这种新的一致性状态也必须持久地保存。
一旦一个事务已提交,则就不能通过中止来清除其操作的影响。唯一能清除一个已提交的事务的影响的方法是执行一个补偿事务。
比如一个向账户加20美元的事务,相应的补偿事务就是从这个账户中扣除20美元。
编写补偿事务是用户的职责,不是数据库的职责。

事务的执行过程

事务开始时处于激活状态。

当事务完成了最后一条语句执行后,事务进入部分已提交的状态。在这个时间点,事务已经完成了执行,但还有可能被中止,因为实际的输出还有可能驻留在主内存中,因此一个硬件故障可能会妨碍这个事务的成功执行。

数据库然后将足够的信息写到硬盘上,这样即使发生了故障,当故障恢复后,系统重启时,由事务所执行的更新可被重新创建的。当最后一条信息被写入硬盘时,事务进入已提交状态

当系统判断事务不能进行正常执行(比如硬件故障、逻辑错误等)后,事务进入已失败的状态。这样的事务必须被回滚。然后事务进入已中止状态。在这个点,系统有两个选择:

  • 重新开始执行事务
    适用于由硬件故障、软件错误导致的事务导致的不能创建;
    不适用于由事务内部逻辑错误导致的不能创建;
    一个重新开始执行的事务是一个新的事务;
  • 杀掉事务
    适用于内部逻辑错误导致的不能创建,这些错误只有通过重写应用程序才能修正;
    适用于输入错误;
    适用于数据库找不到所需数据;

如何实现事务的原子性和持久性

基本思想:充分记录相关日志信息

要保证事务的原子性,一个被中止的事务必须对数据库的状态没有影响。因此,被中止的事务对数据库所做的修改必须被撤销。

一旦一个被中止的事务所做的修改被撤销了,就说这个事务被回滚了。
管理中止事务是恢复计划职责的一部分,通过维护一份日志来管理。

一个事务对数据库所做的每个修改都首先会被记录在这份日志中:记录执行修改的事务的标识符、记录要修改的数据项的标识符、记录数据项修改前的旧值和修改后的新值。只有完成这份日志记录后才能修改数据库本身。

维护这样的日志的作用:

  • 重做一次修改来保证原子性和持久性;
  • 当事务执行出现故障时,撤销一次修改来保证原子性;

如何处理可观察到的外部写操作?

常见的外部写操作有哪些?

  • 写到屏幕上,给用户发邮件等
  • 在ATM机上取钱
  • 在网站上订票
  • 展示激活事务数据给用户等

对于第一类外部写操作,大部分系统的实现都是保证:只有事务进入已提交状态后,才允许这类外部写操作发生。常用的做法是将与外部写操作相关的数据保存在数据库中的一张表里,只有事务进入了已提交状态,才执行外部写操作。如果系统在事务进入已提交状态后,执行外部写操作完成前崩溃了,则当系统重启后,数据库系统会执行外部写操作的。

对于第二类外部写操作,就稍微复杂一点。如果ATM机在准备吐钱的时候崩溃了,则当系统恢复后就不能继续吐钱了,因为这个时候用户可能已经离开了。这个时候可能需要执行补偿事务操作了,当系统恢复后,重新将现金加回用户的账户。

对于第三类外部写操作,有可能正好在订票事务提交后系统崩溃了,也有可能刚好在订票事务提交后,网络连接断开了。无论哪一种情形,事务提交了,但是外部写没有发生。这种情形就要求应用必须设计成:当用户网络连接恢复后,重新连接订票服务时,用户可以看到其是否预订成功。

对于第四类外部写操作,除非能提供保证原子性的补偿事务,否则不允许这类外部写操作。

信息检索

  • 什么是被中止的事务?
  • 怎么处理被中止的事务?
  • 为什么要处理被中止的事务?
  • 什么是事务的回滚?

你可能感兴趣的:(事务的原子性和持久性)