Oracle 11g在数据库建成后,会生成一个undo表空间,undo表空间默认生成一些undo段(一般为10个),同时,system表空间也会生成一个undo段
Oracle的undo主要有如下三个作用:
崩溃恢复
事务回滚
构造CR块(多版本查询)
本文通过一个简单的测试,大致屡一下oracle的一次事务中undo的工作方式
模拟一个事务
1、使用liu用户登录
[oracle@oracle11g ~]$ sqlplus liu/liu
SQL> select * from t1;
ID NAME
---------- --------------------
2 zyr
4 liu
2、开始一个事务
SQL> delete from t1;
2 rows deleted.
接下来主要关注如下三个视图:
1、v$transaction视图
查询数据库当前活跃的事务
select * from v$transaction;
表示该事务使用6号undo段,14号槽位,该槽位第11657次被覆盖。这三个值组成了Xid
2、v$rollstat查看有活跃事务的段
select * from v$rollstat
where XACTS>0;
3、v$rollname视图
select * from v$rollname where usn=6;
根据undo段名dump出这个undo段的段头块
SQL> alter system dump undo header '_SYSSMU6_1263032392$';
System altered.
SQL> select distinct sid from v$mystat;
SID
----------
23
SQL> select paddr from v$session where sid=23;
PADDR
----------------
00000000BA0DBA30
SQL> select spid from v$process where addr='00000000BA0DBA30';
SPID
------------------------
6682
[oracle@oracle11g trace]$ pwd
/u01/app/oracle/diag/rdbms/oracle11g/oracle11g/trace
[oracle@oracle11g trace]$ vim oracle11g_ora_6682.trc
/u01/app/oracle/diag/rdbms/oracle11g/oracle11g/trace
[oracle@oracle11g trace]$ vim oracle11g_ora_6682.trc
********************************************************************************
Undo Segment: _SYSSMU6_1263032392$ (6)
********************************************************************************
找到段头块的事务槽
index state cflags wrap# uel scn dba parent-xid nub stmt_num cmt
0x0e 10 0x80 0x2d89 0x0086 0x0000.006cb904 0x00c05430 0x0000.000.00000000 0x00000001 0x00000000 0
index 槽位号
state 状态,值为10说明14号槽位确实有活跃事务
cflags 0x80未提交,0x00已提交
wrap# 覆盖次数,十六进制数
将其转换成10进制
同时看到dba地址为0x00c05430
dump表的数据块分析事务槽
先查找t1表数据的rowid
SQL> select rowid,id,name from liu.t1;
ROWID ID NAME
------------------ ---------- --------------------
AAAWSKAAEAAABk3AAA 1 liu
然后根据rowid找到block
rowid包含的信息通过dbms_rowid包进行剥离
select dbms_rowid.rowid_object('AAAWSKAAEAAABk3AAA') object_id,
dbms_rowid.rowid_relative_fno('AAAWSKAAEAAABk3AAA') file_id,
dbms_rowid.rowid_block_number('AAAWSKAAEAAABk3AAA') block_id,dbms_rowid.rowid_row_number('AAAWSKAAEAAABk3AAA') row_num from dual;
dump这个数据块,4号文件的6455号块
SQL> alter system dump datafile 4 block 6455;
System altered.
[oracle@oracle11g trace]$ pwd
/u01/app/oracle/diag/rdbms/oracle11g/oracle11g/trace
[oracle@oracle11g trace]$ vim oracle11g_ora_10955.trc
/u01/app/oracle/diag/rdbms/oracle11g/oracle11g/trace
[oracle@oracle11g trace]$ vim oracle11g_ora_10955.trc
Start dump data blocks tsn: 4 file#:4 minblk 6455 maxblk 6455
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0001.00a.0000219a 0x00c00083.01d0.2a C--- 0 scn 0x0000.006cb113
0x02 0x0006.00e.00002d89 0x00c05430.028f.2d ---- 1 fsc 0x0008.00000000
该数据块共有两个事务槽,而当前事务正在使用2号事务槽
数据行的行头dump信息
block_row_dump:
tab 0, row 0, @0x1f84
tl: 2 fb: --HDFL-- lb: 0x2 //表示被2号事务槽占用
dump undo数据块
处理uba地址,得到文件号和块号
先将地址转换为十进制
SQL> select to_number('00c05430','xxxxxxxx') from dual;
TO_NUMBER('00C05430','XXXXXXXX')
--------------------------------
12604464
使用dbms_utility包剥离uba地址信息
select dbms_utility.data_block_address_file(12604464) file_num,
dbms_utility.data_block_address_block(12604464) block_num from dual;
发现undo数据存在于3号文件的21552号block
dump这个查找出的undo block(3,21552)
SQL> alter system dump datafile 3 block 21552;
System altered.
[oracle@oracle11g trace]$ pwd
/u01/app/oracle/diag/rdbms/oracle11g/oracle11g/trace
[oracle@oracle11g trace]$ vim oracle11g_ora_6682.trc
/u01/app/oracle/diag/rdbms/oracle11g/oracle11g/trace
[oracle@oracle11g trace]$ vim oracle11g_ora_6682.trc
Start dump data blocks tsn: 2 file#:3 minblk 21552 maxblk 21552
*** 2015-08-12 11:17:57.998
确实是3号文件21552块,接下来查找我们关注的undo数据
fb: --H-FL-- lb: 0x0 cc: 2
null: --
col 0: [ 2] c1 02
col 1: [ 3] 6c 69 75 //undo数据
使用dump编码对t1表中数据进行转换
select dump(1,1016) clo1,dump('liu',1016) col2 from dual; //16代表16进制,10显示字符集
与dump文件中完全吻合
简单结论:
通过上述测试过程,我们能够看出各个部分的地址对应关系
那么undo机制在一次oracle事务中可用下图做出一个简单的解释