首先我们来了解一下什么是rowid?Rowid 由对象号,数据文件号,数据块号,行号组成,如下图:
现在我以scott用户下面的users表为例,没有的朋友可以自行创建测试
select rowid,dbms_rowid.rowid_object(rowid)robject,
dbms_rowid.rowid_relative_fno(rowid) fno,
dbms_rowid.rowid_block_number(rowid) bno,
dbms_rowid.rowid_row_number(rowid) rno fromusers;
rowid robject fno bno rno
AAASa7AAEAAAAKbAAA 75451 4 667 0
AAASa7AAEAAAAKbAAA 75451 4 667 1
AAASa7AAEAAAAKbAAA 75451 4 667 3
.....
这里就不详解dbms.rowid包了,有兴趣的朋友可以去了解,在以后的文章中我将会给大家讨论。
得到对应的文件号和块号这里为 第75451号对象,4号文件,第667号数据块,行号分别为响应的行
对数据块绝对地址有兴趣的朋友可以参考下面语句:
select dbms_utility.make_data_block_address(4,667)from dual;
当然知道绝对地址也可以知道相对的:
SELECT dbms_utility.data_block_address_block(16777883)"block",dbms_utility.data_block_address_file(16777883)"file" from dual;
这儿扯远了,回到正题
当然你可以这样的找到该表对应的数据块:
select header_file,header_block,blocks,extentsfrom dba_segments where segment_name='USERS' and owner=’SCOTT’;
下面就dump出这个数据块:
Alter system dump datafile 4 block 667;
Dump下的文件应该去哪儿找呢:
Show parameter user_dump_dest;
ok,打开文件,第一次看的同学估计已经晕了,下面贴上我dump出的block,这儿做一个说明,凡是在括号里面的文字,是我对该文件相关属性的解释:
Trace filed:\app\lenovo\diag\rdbms\orcl\orcl\trace\orcl_ora_5516.trc
Oracle Database 11g Enterprise EditionRelease 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Miningand Real Application Testing options
Windows NT Version V6.1 Service Pack 1
CPU : 4 - type 8664, 2 PhysicalCores
Process Affinity : 0x0x0000000000000000
Memory (Avail/Total): Ph:5126M/8142M,Ph+PgF:11106M/16282M
Instance name: orcl
Redo thread mounted by this instance: 1
Oracle process number: 21
Windows thread id: 5516, image: ORACLE.EXE(SHAD)
*** 2013-10-18 09:06:00.314
*** SESSION ID:(67.47) 2013-10-1809:06:00.314
*** CLIENT ID:() 2013-10-18 09:06:00.314
*** SERVICE NAME:(SYS$USERS) 2013-10-1809:06:00.314
*** MODULE NAME:(sqlplus.exe) 2013-10-1809:06:00.314
*** ACTION NAME:() 2013-10-18 09:06:00.314
(上面是数据库和操作系统当前会话的一些信息,相信大部分朋友都能看懂,这里不一一详解了)
Start dump data blocks tsn: 4 file#:4minblk 667 maxblk 667
( tsn:所在表空间编号 file:所在数据文件编号 minblk:数据块开始的编号,maxblk数据块结束的编号。有对表空间号疑问的朋友,可以通过:
select * from v$tablespace wherename=(select tablespace_name from dba_tables where table_name='USERS');
)
Block dump from cache:
Dump of buffer cache at level 4 for tsn=4,rdba=16777883 (rdba:是绝对数据块地址,上面我们已经讨论)
BH (0x000007FF4B3F5B18) file#: 4 rdba:0x0100029b (4/667) class: 1 ba: 0x000007FF4B322000
set: 11 pool 3 bsz: 8192 bsi: 0 sflg: 2 pwc: 43,19
dbwrid: 0 obj: 75451 objn: 75451 tsn: 4 afn: 4 hint: f
hash: [0x000007FF737CE198,0x000007FF737CE198] lru: [0x000007FF4B3F5D30,0x000007FF4B3F5AD0]
obj-flags: object_ckpt_list
ckptq: [0x000007FF729CAEB0,0x000007FF4B3F98D8] fileq:[0x000007FF729CAF30,0x000007FF729CAF30] objq:[0x000007FF6D092890,0x000007FF6D092890]
st:XCURRENT md: NULL tch: 2
flags: buffer_dirty only_sequential_access redo_since_read
LRBA: [0x5f.862.0] LSCN: [0x0.2d556f] HSCN: [0x0.2d556f] HSUB: [1]
crpin refcnt: 0 sh pin refcnt: 0
Block dump from disk:
buffer tsn: 4 rdba: 0x0100029b (4/667)
scn: 0x0000.00269016 seq: 0x06 flg: 0x04tail: 0x90160606
(scn 数据块最后一次编辑记录的系统该编号, TAIL用于验证block的完整性的,它是由SCNBase,block type,SCN seq number组成。数据块的最后四字节tail: 0x90160606=scnBASE+flg+seq,如果不相等会报块损坏!!!
)
frmt: 0x02 chkval: 0x2ba0 type: 0x06=transdata
(frmt 数据块格式,属于哪个版本 chkval 校验写入快在设置和使用oracle检查一致性和有效性 type 定义那种类型的数据块,这里是事务型,用来存放表和索引
Type Meaning
0x02 undo block
0x06 table or index data block
0x0e undo segment header
0x10 data segment header block
0x17 bitmapped data segment header
)
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x000000001A3B7000 to 0x000000001A3B9000
01A3B7000 0000A206 0100029B 0026901604060000 [..........&.....]
01A3B7010 00002BA0 00000001 000126BB00268CA3 [.+.......&....&.]
01A3B7020 00000000 00320002 0100029800000001 [......2.........]
01A3B7030 0000056B 00C00D5B 0006015900000065 [k...[...Y...e...]
01A3B7040 00000000 00000000 0000000000000000 [................]
Repeat 1 times
为了节省空间,中间省略了一些内容
01A3B8FD0 5A0505C1 59584342 0202013C5A0504C1 [...ZBCXY<......Z]
01A3B8FE0 59584342 0202013C 5A0503C1 59584342 [BCXY<......ZBCXY]
Block header dump: 0x0100029b (数据文件头部)
Object id on Block? Y
seg/obj: 0x126bb csc: 0x00.268ca3 itc: 2 flg: E typ: 1 - DATA
brn: 0 bdba: 0x1000298 ver: 0x01opc: 0
inc: 0 exflg: 0
(
seg/obj:0x126bb 为16进制数,转换为10进制数为75451
通过dba_objects视图可以得到:
selectobject_id from dba_objects where object_name=’USERS’ and owner=’SCOTT’;
OBJECT_ID
----------
75451
csc: 0x00.268ca3 the scn of cleanout
itc: 2 表示有两个事物槽
flg: E 指用的是ASSM,如果是0表示用的是freelist
typ: 1 – DATA 数据块的类型 事物型 用于存放表和索引数据
)
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0001.000.0000056b 0x00c00d5b.0159.06 ---- 101 fsc 0x0000.00000000
0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
(事务槽,对应的事务可以查询v$transaction,xid以及uba对应的数据都与v$transaction中的响应字段相同,这里暂不详解
itl:ITL(InterestedTransaction List)事物槽号的流水编号
xid:事物id,由undo的段号+槽号+槽号覆盖次数三部分组成
uba:undo blockaddress 第一段是回滚数据块的地址,包括回滚段文件号和数据块号;第二段是回滚序列号;第三段是回滚记录号。
flag:事务标志位 --代表为提交
C--- = transaction has beencommitted and locks cleaned out
-B-- = this undo recordcontains the undo for this ITL entry
--U- = transaction committed(maybe long ago); SCN is an upper bound
---T = transaction was stillactive at block cleanout SCN
lck:锁住了几行数据,对应有几个行锁
scn/fsc: Scn=SCN of commitedTX; Fsc=Free space credit(bytes)
这里fsc 0x0000.00000000是指提交的scn,这个值大于上次清除块时的scn=csc: 0x00.268ca3 (此scn是这个块中最小的SCN of commited)
SCN WRAP:如果事务已提交并完成清洗,该字段保存事务提交SCN的SCN WRAP部分,否则该字段保存空闲预支字节数(FSC).比如我删除了一行数据10个字节,在事务提前前,这10个字节就属于fsc(即会写到SCN WRAP),只有事务提交后,才能正式返回到空闲空间。
注意:如果你正在对这个表做事务操作,注意lck的值
)
bdba: 0x0100029b (数据块的地址 转换为2进制文件取前10位为文件号,对应的是4号文件,剩余的为块号,对应为667号块)
data_block_dump,data header at 0x1a3b7064
===============
tsiz: 0x1f98 (块的总大小即8088个字节)
hsiz: 0xdc (数据头大小为22个字节)
pbl: 0x1a3b7064 (pointer tobuffer holding the block)
76543210
flag=-------- (N=pcrfreehit(clusters);F=do not put on free list;K=flushable cluster keys)
ntab=1 (表示这个快的数据在一个表)
nrow=101 (表示这个表有101行数据)
frre=-1 (The first free row entry in the row directory=you have toadd one)
fsbo=0xdc (Free space beginoffset 叫起始空间:可以存放数据空间的起始位置(即定义了数据层中空闲空间的起始offset))
fseo=0xff6 (叫结束空间:可以存放数据空间的结束位置(即定义了数据层中空闲空间的结束offset))
avsp=0x19ff (叫空闲空间:定义了数据层中空闲空间的字节数)
tosp=0x19ff (叫最终空闲空间:定义了ITL中事务提交后,数据层中空闲空间的字节数)
0xe:pti[0] nrow=101 offs=0 (整个表的开始,共101行数据 ,定义了该表在行索引中使用的插槽数)
0x12:pri[0] offs=0x14a7(叫行索引,定义了该块中包含的所有行数据的位置)
0x14:pri[1] offs=0x149b
为节省空间,中间省略了数据
0xda:pri[100] offs=0xff6
block_row_dump: (数据块中的数据)
tab 0, row 0, @0x14a7 (第一个表第一行的位置 ,定义了该表在行索引中的起始插槽号)
tl: 12 fb: --H-FL-- lb: 0x1 cc: 2
(--行头,tl: 12行长度12个字节,
fb: (Flag byte)--H-FL指H(Head pieceof row)F(First data piece) L(Last data piece)
lb: 0x1 --Lock byte和上面的ITL的lck相对应,表示这行是否被lock了
cc: 2 --表示有两列,即这个表有两个字段)
col 0: [ 2] c1 02 (第一行的第一个字段长度和值)
col 1: [ 5] 5a 42 43 58 59 (第一行的第二个字段长度和值)
tab 0, row 1, @0x149b
tl: 12 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 2] c1 03
col 1: [ 5] 5a 42 43 58 59
节省空间,中间省略了数据
tab 0, row 100, @0xff6
tl: 13 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 3] c2 02 02
col 1: [ 5] 5a 42 43 58 59
end_of_block_dump
End dump data blocks tsn: 4 file#: 4 minblk667 maxblk 667
对于上面的内容,相信你也是一头雾水,让我们分析其中的数据内容吧:
selectuserid,UTL_RAW.CAST_TO_NUMBER(replace(' c1 02 ',' ')) id1,
username,UTL_RAW.CAST_TO_VARCHAR2(replace('5a42 43 58 59',' ')) name1
from users;
USERID ID1 USERNAME NAME1
------ --------------------------------------------------------------------------------------------------------------
1 1 ZBCXY ZBCXY
2 1 ZBCXY ZBCXY
3 1 ZBCXY ZBCXY
4 1 ZBCXY ZBCXY
5 1 ZBCXY ZBCXY
6 1 ZBCXY ZBCXY
7 1 ZBCXY ZBCXY
当然你也可以将数据转换为16进制看是否对应:
select userid,username,dump(1,'16'),dump('ZBCXY','16') from users;
USERID USERNAME DUMP(1,'16') DUMP('ZBCXY','16')
------ -------------------- ---------------------------------------------
1 ZBCXY Typ=2 Len=2: c1,2 Typ=96 Len=5:5a,42,43,58,59
2 ZBCXY Typ=2 Len=2: c1,2 Typ=96 Len=5:5a,42,43,58,59
………………
需要注意的事项:oracle11g中dump block将会首先去buffer cache中查找,如果无法找到,就去datafile中取,dump操作对buffer cahce和datafile没有任何影响
有的朋友说:
SQL> alter system dump datafile 1 block 300; 从内存中取
SQL> alter system dumpdatafile '/opt/oracle/oradata/R11203/system01.dbf' block 300; 从数据文件取,没有亲测,感兴趣的朋友可以试试。