这篇文章主要描述oracle的回滚机制,篇幅可能较长,因为对于oracle的回滚机制来说,要讨论和描述的实在太多,只能刷选自己认为最有意义的一部分进行深入研究和分享
一、我们来看一个DML语句的处理过程描述
update undotest set object_type='VIEW' where object_type='PROCEDURE';
1.检查shared pool中是否存在相同的语句,如果存在,重用执行计划,执行扫描运算,如果不存在,执行硬解析生成执行计划
2.根据执行计划中的扫描运算,检查undotest表中的相关数据块是否存在buffer cache中,如果不存在则读取到内存中
3.检查数据块中符合object_type='PROCEDURE'条件的记录,如果没有符合条件的行记录,则结束语句,如果存在则进入下一步
4.以当前模式(current)获取符合object_type='PROCEDURE'条件的数据块,准备进行更新
5.在回滚表空间的相应回滚段头的事务表上分配事务槽,这个动作需要记录redo日志
6.从回滚段数据块上创建object_type='PROCEDURE'的前映像数据,这个动作也要记录redo日志
7.修改object_type='VIEW' ,这是DML操作的数据变更,而需要记录redo日志
8.用户提交时,在redo日志中记录提交信息,将回滚段头上的事务表和回滚段数据块标记为非活动,清除修改数据块上的事务信息(也可能延迟清除)。同时必须确保整个事务的redp日志写到磁盘上的日志文件
注意:如果最后用户回滚了事务,oracle从回滚段中将前映像数据提取出来,覆盖被更新的数据块。这个回滚动作本身也需要产生redo日志,因此,我们要知道回滚的代价非常昂贵。
二、不同的DML操作,UNDO BLOCK中保存的前映像内容
INSERT操作,UNDO中只需要保存插入记录的rowid,如果需要回退,通过保存的rowid进行删除即可(后面有案例)
UPDATE操作,UNDO中只需要记录被更新字段的旧值,如果需要回退,只需要通过旧值覆盖更新后的值即可。
DELETE操作,UNDO中必须记录整行的数据,如果需要回退,只需要将这整行的数据重新插入至表中即可。
备注:本文章只对INSERT操作,UNDO中保存的内容进行测试,至于UPDATE、DELETE操作,实验方法基本一致,这里就不再累赘
示例
1.开启事务
SQL> create table tt as select object_name,object_id from dba_objects;
Table created.
SQL> insert into tt values('dddddd',1233456); --执行insert操作
1 row created.
2.检查事务信息和其他一些事务信息
SQL> select HEADER_FILE,HEADER_BLOCK from dba_segments a where segment_name='TT';
HEADER_FILE HEADER_BLOCK
----------- ------------
4 810
SQL> SELECT
2 dbms_rowid.rowid_object(rowid) object_id,
3 dbms_rowid.rowid_relative_fno(rowid) REL_FNO,
4 dbms_rowid.rowid_block_number(rowid) BLOCKNO,
5 dbms_rowid.rowid_row_number(rowid) ROWNO,rowid,object_name
6 FROM tt WHERE object_name='dddddd';
OBJECT_ID REL_FNO BLOCKNO ROWNO ROWID
---------- ---------- ---------- ---------- ------------------
OBJECT_NAME
--------------------------------------------------------------------------------
73430 4 1150 0 AAAR7WAAEAAAAR+AAA
dddddd
SQL> select xidusn,xidslot,xidsqn,ubablk,ubafil,ubarec,to_char(start_scnw,'xxxxxxxx') start_scnw,
2 to_char(start_scnb,'xxxxxxxx') start_scnb, start_scnb+start_scnw*power(2,32) start_scn
3 from v$transaction;
XIDUSN XIDSLOT XIDSQN UBABLK UBAFIL UBAREC START_SCNW START_SCNB START_SCN
---------- ---------- ---------- ---------- ---------- ---------- -------------------- -------------------- ----------
5 21 960 1466 3 7 0 f5520 1004832
根据上面查询获取的事务信息,dump insert事务undo 段头和undo 块
SQL> select name from v$rollname where usn=5;
NAME
------------------------------
_SYSSMU5_1527469038$
3.dump undo 段头和undo 块
SQL> oradebug setmypid;
Statement processed.
SQL> oradebug tracefile_name
/u01/oracle/diag/rdbms/test/test/trace/test_ora_604.trc
SQL> alter system dump undo header '_SYSSMU5_1527469038$';
System altered.
SQL> alter system dump datafile 3 block 1466;
System altered.
UNDO BLK:
xid: 0x0005.015.000003c0 seq: 0x12c cnt: 0x7 irb: 0x7 icl: 0x0 flg: 0x0000
Rec Offset Rec Offset Rec Offset Rec Offset Rec Offset
---------------------------------------------------------------------------
0x01 0x1fa4 0x0