Oracle undo机制拙见

  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;
Oracle undo机制拙见
Oracle undo机制拙见
表示该事务使用6号undo段,14号槽位,该槽位第11657次被覆盖。这三个值组成了Xid

2、v$rollstat查看有活跃事务的段
select * from v$rollstat
       where XACTS>0;
Oracle undo机制拙见

3、v$rollname视图    
select * from v$rollname where usn=6;
Oracle undo机制拙见

根据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

********************************************************************************
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进制
Oracle undo机制拙见
同时看到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;
Oracle undo机制拙见

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
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号事务槽
Oracle undo机制拙见
数据行的行头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;
Oracle undo机制拙见
发现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
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显示字符集  
Oracle undo机制拙见
与dump文件中完全吻合

简单结论:
通过上述测试过程,我们能够看出各个部分的地址对应关系
那么undo机制在一次oracle事务中可用下图做出一个简单的解释
Oracle undo机制拙见

上一篇:小程序排行榜


下一篇:浅谈MySQL5.7 sys schema