资讯专栏INFORMATION COLUMN

Oracle undo探索

IT那活儿 / 3487人阅读
Oracle undo探索

点击上方“IT那活儿”,关注后了解更多内容,不管IT什么活儿,干就完了!!!




概  述

1


undo段又叫rollback段,undo的前身就是rollback,查询undo段。

大家都知道的,修改数据后,没有提交的数据写到硬盘上,修改前的数据放在undo segment上。虽然未提交的数据已经写入硬盘,但另外的会话查询时是从undo segment上读取数据,在事务没有结束前,undo里的数据不会清除。
若事务太大导致undo空间不够,此时这个事务就会失败。



实验前准备

2


查出表内容:


SQL> select * from t2;
ID NA
---------- --
1 A
2 a
3 b
4 c
修改一行记录:
SQL> update t2 set NAME=ab where id=4;
1 row updated.





从逻辑层面获取块数据

3


该表的行数据所在的逻辑文件编号和块编号:


SQL> select dbms_rowid.rowid_relative_fno(rowid) fno,dbms_rowid.rowid_block_number(rowid) bn1 from t2;
FNO BN1
---------- ----------
41    1519940
41    1519940
41    1519940
41    1519940
sys用户操作,查询dump文件路径,是用户进程,所以看user_dump_dest:
SQL> show parameter dump
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
background_core_dump string      partial
background_dump_dest string      /u01/app/oracle/diag/rdbms/ocs
tstdb/ocststdb/trace
core_dump_dest string      /u01/app/oracle/diag/rdbms/ocs
tstdb/ocststdb/cdump
max_dump_file_size string      unlimited
shadow_core_dump string      partial
user_dump_dest string      /u01/app/oracle/diag/rdbms/ocs
tstdb/ocststdb/trace
生成逻辑编号是41,块编号是1519940的dump文件:
SQL> alter system dump datafile 41 block 1519940;
System altered.
查询该session产生的dump文件,或者在没有其他session的前提下,直接看最新的dump文件:
SQL> select distinct sid from v$mystat;
SID
----------
581
SQL> select paddr from v$session where sid=581;
PADDR
----------------
0000000253FCC010
SQL> select spid from v$process where addr=0000000253FCC010;
SPID
------------------------
8212
找到dump文件,下载到本地:
[oracle@ocsdbtest trace]$ pwd
/u01/app/oracle/diag/rdbms/ocststdb/ocststdb/trace
[oracle@ocsdbtest trace]$ ls *8212.trc
ocststdb_ora_8212.trc
用UE打开,主要最后面的:
.................
Start dump data blocks tsn: 42 file#:41 minblk 1519940 maxblk 1519940
.................
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0003.017.002c083b 0x00c004f8.e3f0.06  C--- 0  scn 0x0e73.5c418bf9
0x02 0x0009.010.002c7c61 0x00c0032e.e670.23  ---- 1  fsc 0x0000.00000000
bdba: 0x0a573144
data_block_dump,data header at 0x7f0ea1953a64
===============
tsiz: 0x1f98
hsiz: 0x1a
pbl: 0x7f0ea1953a64
76543210
flag=--------
ntab=1
nrow=4
frre=-1
fsbo=0x1a
fseo=0x1f6f
avsp=0x1f5a
tosp=0x1f5a
0xe:pti[0] nrow=4  offs=0
0x12:pri[0] offs=0x1f90
0x14:pri[1] offs=0x1f88
0x16:pri[2] offs=0x1f80
0x18:pri[3] offs=0x1f6f
block_row_dump:
tab 0, row 0, @0x1f90
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col  0: [ 2] c1 02
col  1: [ 1] 41
tab 0, row 1, @0x1f88
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col  0: [ 2] c1 03
col  1: [ 1] 61
tab 0, row 2, @0x1f80
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col  0: [ 2] c1 04
col  1: [ 1] 62
tab 0, row 3, @0x1f6f
tl: 9 fb: --H-FL-- lb: 0x2 cc: 2
col  0: [ 2] c1 05
col  1: [ 2] 61 62
end_of_block_dump
End dump data blocks tsn: 42 file#: 41 minblk 1519940 maxblk 1519940





从物理磁盘层面获取块数据

4


再次dump绝对文件的内容:


SQL> alter system dump datafile /oradata/ocststdb/TSSXCPMIS01.dbf block 1519940;
System altered.
由于在同一个session下dump的,trc文件也是一样的,再次下载,UE打开:
...............
Start dump data block from file /oradata/ocststdb/TSSXCPMIS01.dbf minblk 1519940 maxblk 1519940
.............
Itl Xid Uba Flag Lck Scn/Fsc
0x01   0x0003.017.002c083b 0x00c00b68.6795.07  C--- 0 scn 0x0e73.5c418bf9
0x02   0x0009.010.002c7c61 0x00c00b68.6795.0b ---- 1 fsc 0x0000.00000000
bdba: 0x0a573144
data_block_dump,data header at 0x7f0ea1953a64
===============
tsiz: 0x1f98
hsiz: 0x1a
pbl: 0x7f0ea1953a64
76543210
flag=--------
ntab=1
nrow=4
frre=-1
fsbo=0x1a
fseo=0x1f6f
avsp=0x1f5a
tosp=0x1f5a
0xe:pti[0] nrow=4  offs=0
0x12:pri[0] offs=0x1f90
0x14:pri[1] offs=0x1f88
0x16:pri[2] offs=0x1f80
0x18:pri[3] offs=0x1f6f
block_row_dump:
tab 0, row 0, @0x1f90
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col  0: [ 2] c1 02
col  1: [ 1] 41
tab 0, row 1, @0x1f88
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col  0: [ 2] c1 03
col  1: [ 1] 61
tab 0, row 2, @0x1f80
tl: 8 fb: --H-FL-- lb: 0x0 cc: 2
col  0: [ 2] c1 04
col  1: [ 1] 62
tab 0, row 3, @0x1f6f
tl: 9 fb: --H-FL-- lb: 0x2 cc: 2
col  0: [ 2] c1 05
col  1: [ 2] 61 62
end_of_block_dump
End dump data block from file /oradata/ocststdb/TSSXCPMIS01.dbf minblk 1519940 maxblk 1519940
这一行意思开始dump文件“/oradata/ocststdb/TSSXCPMIS01.dbf”,块“1519940”:
Start dump data block from file /oradata/ocststdb/TSSXCPMIS01.dbf minblk 1519940 maxblk 1519940
有4行数据:
nrow=4
改行数据有锁,0x2,没锁的是0x0:
tl: 9 fb: --H-FL-- lb: 0x2 cc: 2
最后一行内容是2列:
col  0: [ 2] c1 05
col  1: [ 2] 61 62





从undo段获取块数据

5


截取地址(Uba:0x00c00b68.6795.07),0x和第一个“.”之间内容,00c00b68,这是个16进制的地址,通过这个地址获取文件编号和块编号。

先转换成10进制数:
SQL> select to_number(00c00b68,xxxxxxxxxx) from dual;
TO_NUMBER(00C00B68,XXXXXXXXXX)
----------------------------------
12585832
获取文件编号:
SQL> select dbms_utility.data_block_address_file(12585832) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(12585832)
----------------------------------------------
3
获取块编号:
SQL> select dbms_utility.data_block_address_block(12585832) from dual;
DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(12585832)
-----------------------------------------------
2920
查看当前undo使用的那个表空间:
SQL> show parameter undo_tablespace
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_tablespace string UNDOTBS1
查询UNDOTBS的文件编号:
SQL> select file_id from dba_data_files where tablespace_name=UNDOTBS1;
FILE_ID
----------
3
由此确认通过Uba获取的文件编号的正确。
将这个文件dump出来:
SQL> alter system dump datafile 3 block 2920;
System altered.
地址(Uba:0x00c00b68.6795.07)最后一位是07地址,打开dump文件找到地址为07的,看到它的值是63,即“c”,也就是原数据存放到undo表空间去了:
*-----------------------------
* Rec #0x7 slt: 0x1a objn: 176942(0x0002b32e) objd: 176942  tblspc: 42(0x0000002a)
* Layer: 11 (Row) opc: 1   rci 0x00
Undo type: Regular undo    Begin trans Last buffer split:  No
Temp Object:  No
Tablespace Undo: No
rdba: 0x00000000Ext idx: 0
flg2: 0
*-----------------------------
uba: 0x00c00b68.6795.06 ctl max scn: 0x0e73.5c4ac77d prv tx scn: 0x0e73.5c4ac783
txn start scn: scn: 0x0e73.5c4a9dce logon user: 130
prev brb: 12585831 prev bcl: 0
KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
compat bit: 4 (post-11) padding: 1
op: Z
KDO Op code: URP row dependencies Disabled
xtype: XA flags: 0x00000000 bdba: 0x0a573144 hdba: 0x0a573142
itli: 2  ispac: 0  maxfr: 4858
tabn: 0 slot: 3(0x3) flag: 0x2c lock: 0 ckix: 0
ncol: 2 nnew: 1 size: -1
col  1: [ 1] 63
查出“a”和“b”的ASSIC值:
SQL> select ascii(a) from dual;
ASCII(A)
----------
97
SQL> select ascii(b) from dual;
ASCII(B)
----------
98
将97和98转换成16进制,则是61和62,正式最后一行的内容:
SQL> select to_char(97,XX) from dual;
TO_
---
61
SQL> select to_char(98,XX) from dual;
TO_
---
62





各层面获取的数据对比

6


可以看到第一个dump文件,逻辑文件编号出来的文件,和第二个dump文件,绝对文件编号出来的文件,在最后一行的内容都是一致的:


col  1: [ 2] 61 62
即从内存中读取出来的内容和从硬盘读取出来的内容是一样的,未commit就已经写到磁盘上了。
没提交的数据是有标记的,是有锁的,其他session是查不到的。其他session查询该数据,读到这个块时发现有锁,“tl: 9 fb: --H-FL-- lb: 0x2  cc: 2”,可以看到Lck是“1”,表示有1条数据锁定。




总  结

7


通过dump数据得到验证,表的逻辑数据和磁盘数据都保存的是新数据,undo段里则保存原始数据。



本文作者:胡 伟

本文来源:IT那活儿(上海新炬王翦团队)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/129604.html

相关文章

发表评论

0条评论

IT那活儿

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<