第八章 事务
概念
严格调度
级联回滚, 当中止一个事务时, 需要把读入这个事务写入的元素的事务进行回滚, 并依次进行递归回滚依赖。
可恢复调度, 调度中每一个事务都在它所读取的所有事务提交之后才提交, 则这个调度成为可恢复的
日志的提交记录到达磁盘的顺序必须和他们被写入的顺序时一致的。
避免级联回滚调度(AVOID CASCADING ROLLBACK), 调度中的事务只读取已经提交事务的数据。 不进行脏读。 每一个acr 都是可恢复的。
保证ACR 方式:
- 严格封锁, 直到事务提交或中止提交, 事务才允许释放排他锁
严格调度中块的回滚,
事务T 更新A 到缓冲区, 回滚时, 不需要使用日志的回滚, 把缓冲区直接释放到缓冲区队列,禁止刷到磁盘。
严格调度中元组或对象(比块小)
一个块包含两个或多个事务修改的数据。
方法1, 从磁盘中读取老的值,更新到缓冲区
方法2, 用undo 日志恢复
方法3, 额外维护一个单独的主存日志,
3种方法都不好, 第一种需要额外的磁盘, 第二种方法, 需要查看磁盘上大量日志;方法3, 消耗额外大量内存。
成组提交, 不立即将日志提交记录刷新到磁盘, 避免脏读, 按日志顺序刷新, 提交记录到缓冲区日志中,以后释放锁。
逻辑日志
逻辑日志, 只描述块中的变化。
- 操作时幂等的, 可以操作多次
- 当改动的数据量比较少时, 记录改变的字节及其位置。
- 改变描述简单,易于恢复,但改动量比较大。
- 改变数据库许多字节,但改变不可撤销。
比如位B-树记录逻辑日志, 写入描述变化的简单记录。
从逻辑日志恢复。
死锁
- 即使是两阶段也会导致死锁
- 共享锁升级排他锁, 容易死锁
死锁检测
- 超时,最简单方式
- 等待图, 有向无环图
- 通过时间戳检测死锁, 都是较老的事务占有优势, 并且在实际过程中, 比等待图更容易
- 事务T 等待U 持有锁时
- 等待-死亡方案, 只会等待比较新的事务
- 如果T 比U 老, 允许T 等待U 持有的锁
- 如果U 比T 老, 判断T 死亡, T 将回滚
- 伤害–等待方案, 只会等待比较老的事务
- 如果T 比U 老, 他将伤害U, U 必须回滚并放弃T 需要的锁
- 如果U 比T 老, T 等待U 持有的锁
- 等待-死亡方案, 只会等待比较新的事务
- 事务T 等待U 持有锁时
长事务
有时会出现长事务。需要严格长期锁和无锁控制之间做一个平衡。
saga
- 一系列动作
- 一个图, 其节点是动作节点或终点。
- 有一起点
要求是五环图。
- 可以认为每个动作本身是一个短事务
- 整个事务即任何通向终止结点的路径通过 “补偿事务”机制来管理
补偿事务
saga 中,每一个动作都有一个补偿事务,成为A-1, 将状态回滚到初始状态。
原理: