Oracle undo机制拙见

简介: Oracle 11g在数据库建成后,会生成一个undo表空间,undo表空间默认生成一些undo段(一般为10个),同时,system表空间也会生成一个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;
8a37913677954b2bfd78e5038c1b93906f949011
6bd53d42d564b91619a8149fa97549e9000197f6
表示该事务使用6号undo段,14号槽位,该槽位第11657次被覆盖。这三个值组成了Xid

2、 v$rollstat 查看有活跃事务的段
select * from v$rollstat
       where XACTS>0;
de1721db8c5dae146bdc5079982d13dc8f0ede64

3、 v$rollname视图    
select * from v$rollname where usn=6;
20d23859eba1f553be743edb57d50df2014a22ee

根据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进制
081d31f491f82c60c4933d2003066f700383d66a
同时看到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;
ad7887d759871e1f9fbcb31057f048246da18b11

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号事务槽
acc507e5a6a8398c6c5cf32a520de4153cfbb45b
数据行的行头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;
a292920499d8a4e2bf3fbe6a3f3ba591cf461634
发现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显示字符集  
1b177d61a5141bcaf24130fecaf5fe17a26e8323
与dump文件中完全吻合

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

目录
相关文章
|
SQL Oracle 关系型数据库
Oracle 短时间内误删数据,如何快速找回?(UNDO)
首先,这个短时间内,通常是值 undo 段没有被覆盖,undo 保留的时间为多长呢? 1、需要看 undo_retention 的设置,默认为 900s,也就是 15 分钟。 2、需要看数据库的业务繁忙程度,如果1天切一个归档那种,3天前删的说不定都能用 UNDO 找回来。
|
Oracle 关系型数据库 数据库
|
SQL Oracle 关系型数据库
|
Oracle 关系型数据库 数据库
|
Oracle 关系型数据库