UNDO-----------自深入浅出总结(盖国强)

1

什么是回滚与撤销

假定我们发出了一个更新语句:

UPDATE emp SET sal = 4000 Where empno= 7788;

看一下这个语句是怎样执行的(为了简化描述,我们尽量简化了情况):

1检查 empno=7788 记录在 Buffer Cache 中是否存在,如果不存在则读取到 BufferCache

2在回滚表空间的相应回滚段事务表上分配事务槽,这个操作需要记录 Redo 信息

3从回滚段读入或者在 Buffer Cache 中创建 sal=3000 的前镜像,这需要产生 Redo信息并记入 Redo Log Buffer

4修改 Sal=4000,这是 update 的数据变更,需要记入 Redo Log Buffer

5当用户提交时,会在 Redo Log Buffer 记录提交信息,并在回滚段标记该事务为非激活( inactive)。

在以上事务处理过程中,注意 REDO UNDO 是交替出现的,这两者对于数据库来说都非常重要。

在以上的步骤中, 对于回滚段的操作存在多处,在事务开始时,首先需要在回滚表空间获得一个事务槽,分配空间,然后创建前镜像,此后事务的修改才能进行, Oracle 必须以此来保证事务是可以回退的。

如果用户提交( commit) 了事务, Oracle 会在日志文件记录提交,并且写出日志, 同时会

在回滚段中把该事务标记为已提交,提交事务在回滚段事务表的状态变为 INACIVE,然后该事务所使用的回滚空间可以被重用,回滚段空间是循环使用的;

如果用户回滚( rollback) 事务,则 Oracle 程本身也要产生 Redo,所以回退这个操作是很昂贵的。



2

回滚段存储内容

对于 insert 操作,回滚段只需要记录插入记录的 rowid,如果回退,只需将该记录根据 rowid删除即可;

对于 update 操作,回滚段只需要记录被更新字段的旧值即可(前镜像,回退时通过旧值覆盖新值即可完成回退;

对于 delete 操作, Oracle 则必须记录整行的数据,在回退时,Oracle 通过一个反向操作恢复删除的数据。

通过以上介绍可以简单总结一下:

对于相同数据量的数据操作, 通常 insert 产生最少的UNDO, update 产生的 UNDO 居中, 而 delete 操作产生的 UNDO 最多

这也就是我们经常看到的, 当一个大的 Delete 操作失败或者回滚, 总是需要很长的时间, 并且会有大量的 redo 生成。

所以通常在进行大规模数据删除操作时, 推荐通过分批删除分次?交,以减少对于回滚段的占用和冲击。


3

并发控制与一致性读

允许多用户并发访问是数据库必需满足的功能,那么怎样实现并发访问、控制和数据修改就成为了一个重要问题。

一方面 Oracle 通过锁定机制实现数据库的并发控制;

一方面通过多版本( Multi-versioningModel)模型来进行并发数据访问。

通过多版本架构, Oracle 实现了读取和写入的分离,使得写入不阻塞读取;读取不阻塞修改。这是 Oracle 数据库区别于其他数据库的一个重要特征。

多版本模型在 Oracle 数据库中是通过一致性读来实现的,一致性读也正是回滚表空间的主要作用之一。

Oracle 一方面不允许其他用户读取未提交数据,一方面要保证用户读取的数据要来自同一时间点。

让我们通过下图来看一下什么是 Oracle 的一致性读取( Consistent Reads

假定员工 SCOTT 的薪水为 3000

T1 时间我们在 Session1 查询可以得到这个结果;

T2 时间 Session2 进行更新,将 SCOTT 的薪水增加 1000,并未提交(此时数据在内存中已经修改,该 Buffer 状态变为 Dirty);

T3 时间 Session1 再次查询,注意此时, Oracle 不会允许其他用户看到未提交数据,

所以此时, Oracle 需要通过回滚段记录的前镜像进行一致性读,将 3000 恢复出来提供给用户,这是一致性读的作用;

T4 时间, Session2 提交该更改,此时数据修改被永久化;

T5 时间,其他用户再次查询时,将会看到变化后的数据,也就是“ 4000”


Oracle 内部使用 SCN 作为数据库时钟,这里查询结果集就是根据SCN 来进行判断的,每个数据块头部都会记录一个提交 SCN,当数据更改提交后, 提交 SCN

同时被修改,这个 SCN 在查询时可以用来进行一致性读判断。

在上图所示中,假定查询开始的时间为 T1,则在查询获取的数据块中,如果数据块的提交 SCN 小于 T1,则 Oracle 接受该数据,如果提交 SCN 大于 T1 或者数据被锁定修改尚未记录 COMMIT SCN,则 Oracle 需要通过回滚段构造前镜像来返回结果,这就是一致性读的本质含义。

下图进一步体现了回滚段在一致性读中的重要作用:


4

oracle11gUNDO表空间备份增强

由于 UNDO 表空间在恢复时不可缺少,所以在进行备份时必须备份该表空间,但是我们知道一旦事务提交,修改被确认,则该事务的前镜像被标记为 INACTIVE,其中的信息在恢复时也就不会被用到,如果在备份时能够跳过这些数据,则备份 UNDO 表空间的效率就可以大大提高。

Oracle Database 11g 中,Oracle 引入了一个新的特性 RMAN UNDO 备份优化。

RMAN备份 UNDO 表空间时,提交事务的 UNDO 信息将不再备份,这个特性随 RMAN 强制启用。

在测试中,一个数 G Undo 表空间备份文件的大小仅为数百 K

RMAN> list backup;



List of Backup Sets

===================



BS Key  Type LV Size       Device Type Elapsed Time Completion Time

------- ---- -- ---------- ----------- ------------ ---------------

1       Full    1.10G      DISK        00:00:11     31-MAR-16     

        BP Key: 1   Status: AVAILABLE  Compressed: NO  Tag: TAG20160331T151118

        Piece Name: /u01/app/oracle/fast_recovery_area/PROD1/backupset/2016_03_31/o1_mf_nnndf_TAG20160331T151118_chsmdpm6_.bkp

  List of Datafiles in backup set 1

  File LV Type Ckp SCN    Ckp Time  Name

  ---- -- ---- ---------- --------- ----

  1       Full 1052033    31-MAR-16 /u01/app/oracle/oradata/prod1/system01.dbf

  2       Full 1052033    31-MAR-16 /u01/app/oracle/oradata/prod1/sysaux01.dbf

  3       Full 1052033    31-MAR-16 /u01/app/oracle/oradata/prod1/undotbs01.dbf

  4       Full 1052033    31-MAR-16 /u01/app/oracle/oradata/prod1/users01.dbf

  5       Full 1052033    31-MAR-16 /u01/app/oracle/oradata/prod1/example01.dbf


BS Key  Type LV Size       Device Type Elapsed Time Completion Time

------- ---- -- ---------- ----------- ------------ ---------------

2       Full    9.36M      DISK        00:00:03     31-MAR-16     

        BP Key: 2   Status: AVAILABLE  Compressed: NO  Tag: TAG20160331T151118

        Piece Name: /u01/app/oracle/fast_recovery_area/PROD1/backupset/2016_03_31/o1_mf_ncsnf_TAG20160331T151118_chsmf8q3_.bkp

  SPFILE Included: Modification time: 31-MAR-16

  SPFILE db_unique_name: PROD1

  Control File Included: Ckp SCN: 1052033      Ckp time: 31-MAR-16


BS Key  Type LV Size       Device Type Elapsed Time Completion Time

------- ---- -- ---------- ----------- ------------ ---------------

3       Full    5.58M      DISK        00:00:00     31-MAR-16     

        BP Key: 3   Status: AVAILABLE  Compressed: NO  Tag: TAG20160331T151301

        Piece Name: /u01/app/oracle/fast_recovery_area/PROD1/backupset/2016_03_31/o1_mf_nnndf_TAG20160331T151301_chsmhx9b_.bkp

  List of Datafiles in backup set 3

  File LV Type Ckp SCN    Ckp Time  Name

  ---- -- ---- ---------- --------- ----

  3       Full 1052033    31-MAR-16 /u01/app/oracle/oradata/prod1/undotbs01.dbf



5

回滚机制的深入研究

1DML 更新事务开始

我们重新来看这个更新语句:

SQL> conn scott/oracle

Connected.

SQL> select * from emp;


     EMPNO ENAME      JOB               MGR HIREDATE            SAL

---------- ---------- --------- ---------- --------- ----------

      COMM     DEPTNO

---------- ----------

      7369 SMITH      CLERK              7902 17-DEC-80            800

   20


      7499 ALLEN      SALESMAN              7698 20-FEB-81           1600

       300           30

。。。。。

14 rows selected.

SQL> select sal from emp where empno=7788;


       SAL

----------

10


SQL> update emp set sal=4000 where empno=7788;


1 row updated.


SQL> select * from emp where empno=7788;


     EMPNO ENAME      JOB               MGR HIREDATE            SAL

---------- ---------- --------- ---------- --------- ----------

      COMM     DEPTNO

---------- ----------

      7788 SCOTT      ANALYST              7566 19-APR-87           4000

   20

如果我没有提交更新的这个操作,此时另一个用户需要查询empno=7788的工资,会发生什么情况呢?

SQL> select * from emp where empno=7788;


     EMPNO ENAME      JOB               MGR HIREDATE            SAL       COMM

---------- ---------- --------- ---------- --------- ---------- ----------

    DEPTNO

----------

      7788 SCOTT      ANALYST              7566 19-APR-87             10

20

如果这个时候我提交了刚刚的更新操作,此时另一个用户再查时又会怎么样呢?

SQL> commit

  2  ;


Commit complete.

SQL> select * from emp where empno=7788;


     EMPNO ENAME      JOB               MGR HIREDATE            SAL       COMM

---------- ---------- --------- ---------- --------- ---------- ----------

    DEPTNO

----------

      7788 SCOTT      ANALYST              7566 19-APR-87           4000

20




2.获得事物信息

先不提交这个事务,在另外窗口新开 Session,使用 SYS 用户查询相关信息,进行进一步的分析研究。

SQL>  SELECT xidusn, xidslot, xidsqn, ubablk, ubafil, ubarec FROM v$transaction;


    XIDUSN    XIDSLOT          XIDSQN     UBABLK        UBAFIL           UBAREC

---------- ---------- ---------- ---------- ---------- ----------

 6           31            1096      10819             3               13

从事务表中我们可以获得关于这个事务的信息,该事务位于 6 号回滚段( XIDUSN),在6 号回滚段上,该事务位于第 31 号事务槽( XIDSLOT):


SQL> select usn,writes,rssize,xacts,hwmsize,shrinks,wraps from v$rollstat;


       USN     WRITES          RSSIZE      XACTS    HWMSIZE          SHRINKS      WRAPS

---------- ---------- ---------- ---------- ---------- ---------- ----------

 0         5408          385024          0        385024                0           0

 1          544         1499136          0    1499136                0           0

 2          968         2285568          0    2285568                0           0

 3          708         3530752          0    3530752                0           0

 4          702         4186112          0    4186112                0           0

 5          712         1433600          0    1433600                0           0

 6          586         2285568          1    2285568                0           0

 7          390         1171456          0    1171456                0           0

 8         1892         4186112          0    4186112                0           0

 9          452         1302528          0    1302528                0           0

10          394          319488          0        319488                0           0


11 rows selected.

V$ROLLSTAT 视图中也可以获得事务信息, XACTS 字段代表的是活动事务的数量,同样我们看到该事务位于 6 号回滚段:


3获得回滚段名称并转储段头信息

查询 V$ROLLNAME 视图获得回滚段名称,并转储回滚段头信息:

SQL>  select * from v$rollname a where a.usn=6;


       USN NAME

---------- ------------------------------

 6 _SYSSMU6_1263032392$



6

事物的基本流程

1首先当一个事务开始时,需要在回滚段事务表上分配一个事务槽

2在数据块头部获取一个 ITL 事务槽,该事务槽指向回滚段头的事务槽

3在修改数据之前,需要记录前镜像信息,这个信息以 UNDO RECORD 的形式存储在回滚段中,回滚段头事务槽指向该记录

4锁定修改行,修改行锁定位( lb-lock byte)指向 ITL 事务槽

5数据修改可以进行


7        

ORA-01555 错误

看一下下图的描述: 假定在时间 T 用户 A 发出一条更新语句,更新 SCOTT 用户的 SAL

用户 B Ty 时间发出查询语句,查询 SCOTT 用户的 SAL用户 A 的更新在 Tx 时间提交

提交可能为快速提交清除,也可能是延迟块清除;用户 B 的查询在 Tz 时间输出

我们来看一下数据库在不同情况下的内部处理。

1如果 Ty < T< Tz <Tx,那么查询需要构造一致性读,由于事务尚未提交,可以通过回滚段构造前镜像,完成一致性读取

2如果 Ty < T < Tx < Tz, 由于 Ty 查询时间小于 T 事务更新时间,那么数据库需要构造一致性读取,而 Tz 查询完成时间大于 Tx 提交时间,那么前镜像就有可能被覆盖,不可获取。

如果 Tx 交方式为 Fast Block Cleanout致性读 ORA-01555 错误。

如果 Tx 交方式为 Delayed Block Cleanout,那么回滚段信息不可用时 Oracle将无法判断 Ty Tx 的时间先后关系。

如果 Ty>Tx,那么 Oracle 可以正常进行块清除,并将块清除后的数据返回给用户 B

如果 Ty<T,那么 Oracle 需要继续构造一致性读返回给用户 BOracle 无法判断这两种情况, 就会出现延迟块清除

ORA-01555 错误

ORA-01555 的直观解释是“ Snapshot too old”,也就是快照太旧,其根本含义就是查询需要的前镜像过于“久远”,已经无法找到了。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30606702/viewspace-2073185/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/30606702/viewspace-2073185/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值