《数据库实现》-- 第八章 事务

第八章 事务

概念

严格调度

级联回滚, 当中止一个事务时, 需要把读入这个事务写入的元素的事务进行回滚, 并依次进行递归回滚依赖。 

可恢复调度, 调度中每一个事务都在它所读取的所有事务提交之后才提交, 则这个调度成为可恢复的
日志的提交记录到达磁盘的顺序必须和他们被写入的顺序时一致的。 

避免级联回滚调度(AVOID CASCADING ROLLBACK), 调度中的事务只读取已经提交事务的数据。 不进行脏读。 每一个acr 都是可恢复的。 

保证ACR 方式:

  1. 严格封锁, 直到事务提交或中止提交, 事务才允许释放排他锁

image.png
严格调度中块的回滚, 
事务T 更新A 到缓冲区, 回滚时, 不需要使用日志的回滚, 把缓冲区直接释放到缓冲区队列,禁止刷到磁盘。 

严格调度中元组或对象(比块小)
一个块包含两个或多个事务修改的数据。
方法1, 从磁盘中读取老的值,更新到缓冲区
方法2, 用undo 日志恢复
方法3, 额外维护一个单独的主存日志, 

3种方法都不好, 第一种需要额外的磁盘, 第二种方法, 需要查看磁盘上大量日志;方法3, 消耗额外大量内存。 

成组提交, 不立即将日志提交记录刷新到磁盘, 避免脏读, 按日志顺序刷新, 提交记录到缓冲区日志中,以后释放锁。 

逻辑日志

逻辑日志, 只描述块中的变化。 

  1. 操作时幂等的, 可以操作多次
  2. 当改动的数据量比较少时, 记录改变的字节及其位置。
  3. 改变描述简单,易于恢复,但改动量比较大。 
  4. 改变数据库许多字节,但改变不可撤销。

 

比如位B-树记录逻辑日志, 写入描述变化的简单记录。 

从逻辑日志恢复。 

死锁

  1. 即使是两阶段也会导致死锁
  2. 共享锁升级排他锁, 容易死锁

死锁检测

  1. 超时,最简单方式
  2. 等待图,  有向无环图
  3. 通过时间戳检测死锁, 都是较老的事务占有优势, 并且在实际过程中, 比等待图更容易
    1. 事务T 等待U 持有锁时
      1. 等待-死亡方案, 只会等待比较新的事务
        1. 如果T 比U 老, 允许T 等待U 持有的锁
        2. 如果U 比T 老, 判断T 死亡, T 将回滚
      2. 伤害–等待方案, 只会等待比较老的事务
        1. 如果T 比U 老, 他将伤害U, U 必须回滚并放弃T 需要的锁
        2. 如果U 比T 老, T 等待U 持有的锁

长事务

有时会出现长事务。需要严格长期锁和无锁控制之间做一个平衡。

saga

  1. 一系列动作
  2. 一个图, 其节点是动作节点或终点。
  3. 有一起点

要求是五环图。

  1. 可以认为每个动作本身是一个短事务
  2. 整个事务即任何通向终止结点的路径通过 “补偿事务”机制来管理

 

补偿事务

saga 中,每一个动作都有一个补偿事务,成为A-1, 将状态回滚到初始状态。

原理:
image.png