文章目录
1.事务涉及到的元素
数据库通常由元素构成
- 通常, 1 元素 = 1 磁盘块 = 1 内存页/块
- 可以更小,=1 记录 或更大 =1 关系
每个事务都会读/写某些元素
每个事务都以提交或者撤销结束
- COMMIT:事务提交
- ABORT:事务撤销
DBMS需要保证事务的:
- 持久性:已提交的事务对数据库产生的影响是持久的,未提交的事务对数据库不应有影响。
- 原子性:事务的所有操作,要么全都执行,要么全都不执行。
2.不同的缓冲区策略会影响事务的持久性
缓冲区处理策略
- Force: 内存中的数据最晚在commit的时候写入磁盘。
- No force: 内存中的数据可以一直保留,在commit之后过一段时间再写入磁盘。
- No steal: 不允许在事务commit之前把内存中的数据写入磁盘。
(此时在系统崩溃的时候可能还没写入到磁盘,需要Redo)。–灵活 - Steal: 允许在事务commit之前把内存中的数据写入磁盘。
(此时若系统在commit之前崩溃时,已经有数据写入到磁盘了,要恢复到崩溃前的状态,需要Undo)。–灵活
3.事务故障会影响事务的原子性
Begin TRANSACTION
READ(A,t);
t:=t*2;
WRITE(A,t);
READ(B,t);
t:=t*2;
WRITE(B,t)
COMMIT;
End TRANSACTION
4.怎样记录日志?
一个包含日志记录的只能追加的顺序文件, 不同事务的日志记录交错存储,按发生时间存储
- 发生系统故障时,使用日志进行恢复:
故障时已提交的事务,重做(Redo)
故障时未提交的事务,撤销(Undo)
日志记录的信息
<Start T>,表示事务T已经开始
<Commit T>,表示事务T成功完成
<Abort T>,事务T未成功,被中止
<T, X, v1> 或者 <T, X, v2> 或者 <T, X, v1,v2>
表示事务T改变了数据库元素X,X原来的值为v1(X的旧值),X新的值为v2.
- 三种日志: Undo型日志, Redo型日志, Undo/Redo型日志
记录内容和记录次序不同,恢复策略也不同
缓冲区处理策略与日志/恢复策略的关系
5.Undo型日志及其故障恢复
Undo型日志
- 对于任一事务T,按下列顺序向磁盘输出T的日志信息:
首先, <T, X, v>被写到日志中(把更新前的值写入磁盘)
其次,OUTPUT(X) (把缓冲区的内容写入磁盘)
最后, <COMMIT T>或<ABORT T>被写到日志中
- 注意:Undo型日志仅保留旧值。<T, X, v>,v为X原来的值(X的旧值)
- Undo型日志:“将事务改变的所有数据写到磁盘前不能提交该事务”
- eg:Undo型日志
利用undo型日志进行恢复 - 首先,确定每一个事务是否已完成?
<STARTT>….<COMMITT>….=yes
<STARTT>….<ABORTT>…….=no(已结束,但未完成)
<STARTT>……………………… =no
- 然后,从日志的尾部开始按日志记录的反序,处理每一日志记录,撤销未完成事务的所有修改
<COMMITT>:标记T已完成
<ABORTT>:标记T已结束但未完成
<T,X,v>: 如果T未完成,则将X=v写回磁盘;否则跳过;
<STARTT>:跳过
-
因事务未提交。通过日志恢复A=8, B=8,保证了事务的原子性
-
因事务已提交。无需做任何事情,已保证了事务的原子性
检查点 -
为什么需要检查点?
(1)因为并不知道处理到日志的哪一个位置才能结束
(2)若在恢复过程中,发生故障怎么办? -
静止检查点:周期性地对日志设置检查点
(1)停止接受新的事务, 等到所有当前活跃事务提交或终止,并在日志中
写入了COMMIT或ABORT记录后
(2)将日志刷新到磁盘,写入日志记录,并再次刷新日志 -
非静止检查点(动态检查点)
(1)在设置检查点时不必关闭系统, 允许新事务进入
(2)写入一条**<START CKPT(T1,…,Tk)>**
其中T1,…,Tk 是所有活跃的未结束的事务
(3)继续正常的操作,直到T1,…,Tk都完成时,写入<END CKPT> -
eg:静态检查点
-
eg:非静态检查点
6.Redo型日志及其故障恢复
Redo型日志
- Undo型日志的问题“将事务改变的所有数据写到磁盘前不能提交该事务”—如何解决?
- 对于任一事务T,按下列顺序向磁盘输出T的日志信息:
首先,<T, X, v>被写到日志中(更新后的值)
其次,<COMMIT T>被写到日志中
最后,OUTPUT(X)
- 注意:redo型日志保留新值。<T, X, v>,v为X更新后的值(X的新值)
- 注意:与undo型的差别,在后两步,先写提交记录后输出,还是先输出,再写提交记录。
- eg:Redo型日志
利用redo日志进行恢复
- 确定每一个事务是否已完成?
<STARTT>….<COMMITT>….=yes
<STARTT>….<ABORTT>…….=no(已结束,但未完成)
<STARTT>……………………… =no
- 从日志的起始位置开始按日志记录的正序处理每一日志记录,重做已提交事务的所有修改:
<COMMITT>:标记T已完成
<ABORTT>:标记T已结束但未完成
<T,X,v>: 如果T已完成,则将X=v写回磁盘;否则跳过;
<STARTT>:跳过
- eg:因事务未提交。原始的A=8, B=8,并未被改动。<T,A,16>等被跳过
- eg:因事务已提交。按次序用<T,A,16><T,B,16>等的新值更新数据库
检查点
非静止检查点
(1)在进行检查点设置时不必关闭系统,允许新事务进入
(2)写入一条<START CKPT(T1,…,Tk)>
其中T1,…,Tk 是所有活跃的未结束的事务
(3)将所有已提交的事务写回磁盘,
(4)继续正常的操作,直到T1,…,Tk都完成时,写入<END CKPT>
- 检查点及应用