独立Undo是oracle数据库战胜其他数据库的关键原因,下面来看看oracle是如何利用undo:
1,先创建一个表,并插入数据,然后更新数据,但并不提交;
SQL> createtable t(id int,name varchar2(10));
表已创建。
SQL> insertinto t values(1,'a');
已创建 1 行。
SQL> insertinto t values(2,'b');
已创建 1 行。
SQL> commit;
提交完成。
SQL> update tset name='c
2 'where id=1;
已更新 1 行。
2,新开一个窗口查询表t的数据,这里最多有三种情况:1,原数据;2,新数据;3,阻塞;其他数据库跟新后都看不到原来的数据,而oracle则让用户看到原数据,这便是oracle的强大之处之一。下面我们通过dump文件来导出数据查看
SQL> select id,name,rowid from t;
ID NAME ROWID
---------- -------------------- ------------------
1 hl AAANYgAAFAABkpFAAA
--通过oracle提供的包查询表t所在的文件号及块号
SQL> select id,name,dbms_rowid.rowid_relative_fno(rowid)fno,dbms_rowid.rowid_bl
ock_number(rowid) bno from t;
ID NAME FNO BNO
---------- -------------------- ---------- ----------
1 c 5 412229
2 b 5 412229
注:dump出来的文件可以通过以下的sql语言查询出来:
执行必须在当前session下执行;
selectdecode(instr(c.VALUE,'/',1),1,c.VALUE||'/',c.VALUE||'\')||d.INSTANCE_NAME||'_ora_'||a.SPID||'.trc'
from v$process a,v$sessionb,v$parameter c,v$instance d
where a.ADDR=b.PADDR andc.NAME='user_dump_dest' and b.AUDSID=userenv('sessionid');
执行必须在当前session下执行;
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0002.01b.00000444 0x008000ac.0269.0e C--- 0 scn 0x0000.095ec11b
0x02 0x0008.002.00000401 0x00800a2d.01d0.04 ---- 1 fsc0x0000.00000000
data_block_dump,data header at 0x7cb2264
===============
tsiz: 0x1f98
hsiz: 0x16
pbl: 0x07cb2264
bdba: 0x01464a45
76543210
flag=--------
ntab=1
nrow=2
frre=-1
fsbo=0x16
fseo=0x1f7f
avsp=0x1f70
tosp=0x1f70
0xe:pti[0] nrow=2 offs=0
0x12:pri[0] offs=0x1f7f
0x14:pri[1] offs=0x1f88
block_row_dump:
tab 0, row 0, @0x1f7f
tl: 9 fb: --H-FL-- lb: 0x2 cc: 2
col 0: [ 2] c1 02
col 1: [ 2] 63
tab 0, row 1, @0x1f88
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 2] c1 03
col 1: [ 1] 62
end_of_block_dump
End dump data blocks tsn: 6 file#: 5 minblk 412229 maxblk 412229
从dump出的文件们可以发现数据的值已经改变,a对应的ascii码为61,而dump出的为63。
为什么另一个session中读到的确是61(a)呢?
因为oracle在这一列上添加了一个锁如图:lb:0x2(lb:lock bytes),在读取数据时oracle会去读0x02对应的uba(undo block address)flag 为---- 对应的这一行;
--获取数据文件号
SQL> select dbms_utility.data_block_address_file(8391213) fromdual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(8391213)
---------------------------------------------
2
--获取块号
SQL> select dbms_utility.data_block_address_block(8391213) fromdual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(8391213)
----------------------------------------------
2605
将这个块dump出来和上面的对比。
uba: 0x00800a2d.01d0.03 ctl max scn: 0x0000.095ebbc6 prv tx scn: 0x0000.095ebbde
txn start scn: scn: 0x0000.095ec11b logon user: 57
prev brb: 8391209 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
op: Z
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x01464a45 hdba: 0x01464a43
itli: 2 ispac: 0 maxfr: 4858
tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 8
ncol: 2 nnew: 1 size: -1
col 1: [ 1] 61
End dump data blocks tsn: 1 file#: 2 minblk 2605 maxblk 2605
Col 1:[1] 61及对应的就是a。
查询数据文件号为2的正是undo数据文件。
SQL> select df.file_name,df.file_id,df.tablespace_name,sp.contents
2 from dba_data_files df,dba_tablespaces sp where df.tablespace_name=sp.tab
space_name;
FILE_NAME FILE_ID TABLESPACE_NAME CONTENTS
------------------------------ ---------- --------------- - -----------------
F:\ORACLE\PRODUCT\10.2.0\ORADATA\ZXNTAGL\USERS01.DBF 4 USERS PERMANENT
F:\ORACLE\PRODUCT\10.2.0\ORADATA\ZXNTAGL\SYSAUX01.DBF 3 SYSAUX PERMANENT
F:\ORACLE\PRODUCT\10.2.0\ORADATA\ZXNTAGL\UNDOTBS01.DBF 2 UNDOTBS1 UNDO
F:\ORACLE\PRODUCT\10.2.0\ORADATA\ZXNTAGL\SYSTEM01.DBF 1 SYSTEM PERMANENT
F:\ORACLE\PRODUCT\10.2.0\DATAFILE\ZXNTAGL_TS_DATA_TAGL.DAT 5 ZXNTAGL_TS_DATA_TAGL PERMANENT
F:\ORACLE\PRODUCT\10.2.0\ORADATA\ZXNTAGL\TEST.DBF 6 TEST PERMANENT