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 | 回滚机制的深入研究 1. 从 DML 更新事务开始 我们重新来看这个更新语句: 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 需要继续构造一致性读返回给用户 B; Oracle 无法判断这两种情况, 就会出现延迟块清除 ORA-01555 错误
ORA-01555 的直观解释是“ Snapshot too old”,也就是快照太旧,其根本含义就是查询需要的前镜像过于“久远”,已经无法找到了。 |
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30606702/viewspace-2073185/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/30606702/viewspace-2073185/