1回滚与撤销
Refer:《深入解析oracle》by eygle
(1) 为了多用户的读一致性和能回退事务,oracle提供了为修改的数据保存修改之前的旧值。
(2) Redo:保证在故障时事务可以恢复
Undo:保证事务可以被回滚或撤销
(3) 9i之前,oracle提供回滚段(rollback)来撤销数据;之后,oracle使用undo表空间来管理。
(4) 下面这个例子是介绍9i前,是如何保证可以回滚的。
Update emp set sal=4000 where empno=7788;
简单看一下这个语句的执行过程:
A:检查empno=7788记录在database buffer cache中是否存在;否,则读取到database buffer cache中。
B:在回滚表空间的相应回滚段事务表上分配事物槽,这个操作需要记录redo信息。
C:在回滚段读入或者在database buffer cache中创建sal=3000的旧值,这需要产生redo信息并记入redo log buffer。
【B,C这两步保证了事务的可回滚性,此后事务的修改才能进行】
D:修改sal=4000,这是update的数据变更,需要记录redo log buffer。
F:当用户提交时,会在redo log buffer记录提交信息,并在回滚段标记该事务为非激活(inactive)。
(5) 如果用户回滚(rollback)事务,则oracle需要从回滚段中把旧值读取出来,修改database buffer cache,完成rollback,这个过程本身会产生redo,so回滚是expensive。
(6) 回滚段在undo表空间中分配,其作用:回退事务,事务恢复,提供读一致性。
对于DML:
Insert:回滚段只需记录插入的记录的rowid;
Update:回滚段只需记录被更新字段的旧值;
Delete:oracle必须记录整行的数据
所以,对产生undo的情况看,delete产生的undo最多,推荐对大规模数据删除操作时,分批删除,分次提交,以减少对回滚段的占用和冲击。
(7) oracle区别于其他数据库的一个重要的特征:
通过多版本架构,oracle实现了读取和写入的分离,使得写入不阻塞读取,读取不阻塞写入。
多版本架构是通过一致性读来实现的。
假定scott的薪水为3000:
A:t1时刻我们在session 1 查询可以得到3000;
B:t2时刻session 2进行update,但未提交(此时数据在database buffer cache中已经修改,该buffer为dirty)
C:t3时刻