一. DUMP DatafileBlock 示例
Oracle的一个数据块里的SCN有三种,分别是块头的SCN, CSC (cleanout SCN)和ITL中记录的commit SCN。 如果我们想查看某个或者某些block 里的内容,可以把这些block dump出来查看。
关于这个dump 方法,在之前的blog里有说明:
Oracle rdba和 dba 说明
http://blog.csdn.net/tianlesoftware/article/details/6529346
OraceITL(Interested Transaction List) 说明
http://www.cndba.cn/Dave/article/1397
根据Rowid 查询对应的block number 和datafile number:
SQL> SELECT
2dbms_rowid.rowid_relative_fno(rowid) REL_FNO,
3dbms_rowid.rowid_block_number(rowid) BLOCKNO,
4dbms_rowid.rowid_row_number(rowid) ROWNO,
5 empno, ename
6 FROM emp WHERE empno = 7369;
REL_FNO BLOCKNO ROWNO EMPNOENAME
---------- -------------------- ---------- ----------
4 20 0 7369 SMITH
然后根据block id执行dump 命令:
SQL> alter system dump datafile 4 block 20;
如果要dump 多个block,命令如下:
SQL>ALTER SYSTEM dump datafile
SYS@anqing2(rac2)> oradebug setmypid
Statement processed.
SYS@anqing2(rac2)> alter system dump datafile 1 block 292689;
System altered.
SYS@anqing2(rac2)> oradebug tracefile_name
/u01/app/oracle/admin/anqing/udump/anqing2_ora_32276.trc
[oracle@rac2 ~]$ cat /u01/app/oracle/admin/anqing/udump/anqing2_ora_32276.trc
*** 2011-08-01 17:51:31.366
Start dump data blocks tsn: 0file#: 1 minblk 292689 maxblk 292689
buffer tsn: 0 rdba: 0x00447751(1/292689)
-- buffertsn: 数据文件对应的tablespace 的 number ,这只是dump文件中记录的数据而已,block 中是没有记录tablespace 的 number 的
scn: 0x0000.005bdee1 seq: 0x01flg: 0x06 tail: 0xdee10601
frmt: 0x02 chkval: 0xaf6f type:0x06=trans data
Hex dump of block: st=0,typ_found=1
Dump of memory from 0x0DC34400to 0x0DC36400
DC34400 0000A206 00447751005BDEE1 06010000 [....QwD...[.....]
......
DC363F0 C3040203 04261C0B65766164 DEE10601 [......&.dave....]
Block header dump: 0x00447751
Object id on Block? Y
seg/obj: 0xd5ec csc: 0x00.5bcbe0 itc: 3 flg: - typ: 1 - DATA
fsl: 0 fnx: 0x0 ver: 0x01
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x000e.007.00000236 0x00000000.0000.00 C-U- 0 scn 0x0000.005b1f7f
0x02 0x000c.005.000003b4 0x01401727.0144.13 C--- 0 scn 0x0000.005bbf0b
0x03 0x0011.007.00000406 0x0140015b.00c7.57 --U- 483 fsc 0x0000.005bdee1
data_block_dump,data header at0xdc34474
-- 其实这个block不是直接从data buffer 中 dump 出来的,这个表示真正dump时 block 的数据区的起始位置,也就是下面这部分开始的位置
===============
tsiz: 0x1f88
-- tsiz: hsiz: pbl: bdba: 在数据文件都是没有存储的
--Total data area size
--8k的block: 8192-20(blockhead)-24(Transaction Header)-24*3(一个事务条)-4(block tail)=8072(0x1f88)
--将十六进制转换为10进制
SYS@anqing2(rac2)> selectto_number('1f88','xxxx') from dual;
TO_NUMBER('1F88','XXXX')
------------------------
8072
hsiz: 0x3d8
--Data headersize
pbl: 0x0dc34474
-- Pointer tobuffer holding the block
bdba: 0x00447751
76543210
flag=--------
ntab=1
nrow=483
frre=-1
fsbo=0x3d8
fseo=0x706
avsp=0x32e
tosp=0x32e
0xe:pti[0] nrow=483 offs=0
0x12:pri[0] offs=0x1f7b
0x14:pri[1] offs=0x1f6e
......
0x3d4:pri[481] offs=0x713
0x3d6:pri[482] offs=0x706
block_row_dump:
tab 0, row 0, @0x1f7b
tl: 13 fb: --H-FL-- lb:0x3 cc: 2
col 0: [ 4] c3 0b 1c 26
col 1: [ 4] 64 61 76 65
tab 0, row 1, @0x1f6e
tl: 13 fb: --H-FL-- lb:0x3 cc: 2
col 0: [ 4] c3 0b 1c 27
col 1: [ 4] 64 61 76 65
tab 0, row 2, @0x1f61
tl: 13 fb: --H-FL-- lb:0x3 cc: 2
col 0: [ 4] c3 0b 1c 28
col 1: [ 4] 64 61 76 65
......
tab 0, row 481, @0x713
tl: 13 fb: --H-FL-- lb:0x3 cc: 2
col 0: [ 4] c3 0b 21 13
col 1: [ 4] 64 61 76 65
tab 0, row 482, @0x706
tl: 13 fb: --H-FL-- lb:0x3 cc: 2
col 0: [ 4] c3 0b 21 14
col 1: [ 4] 64 61 76 65
--这里的row482 之类的都是每一条记录里的具体值。我dump 这个block 保存的记录比较简单,只有2列值。 可以将这个值转换成具体的字符串。 方法如下:
SYS@anqing2(rac2)> setserveroutput on
SYS@anqing2(rac2)> declare nnumber;
2 begin
3 dbms_stats.convert_raw_value('c30b2114',n);
4 dbms_output.put_line(n);
5 end;
6 /
103219
PL/SQL procedure successfullycompleted.
SYS@anqing2(rac2)> declarestr varchar2(100);
2 begin
3 dbms_stats.convert_raw_value('64617665',str);
4 dbms_output.put_line(str);
5 end;
6 /
dave --这个就是 col 1: [ 4] 64 61 76 65 对应的值
PL/SQL procedure successfullycompleted.
end_of_block_dump
End dump data blocks tsn: 0file#: 1 minblk 292689 maxblk 292689
[oracle@rac2 ~]$
二.Datafile Block 格式说明
在网上找到一篇介绍datafile block 格式的文章。 讲的很详细,原文连接,现在以无从确定。 感谢那些前辈们的总结。
目前较为清楚的一个版本如下链接如下:
http://www.sosdb.com/article/datafile_block.htm
注意:
这里的offset地址是指显示的这行内容在它所属于的数据文件里的偏移量,跟Oracle的块啥关系也没有,实际上,用ultraEdit打开任意一个二进制文件,显示内容的最左边就是这行内容的偏移量。如:
该部分占用20 bytes, 为block head
(1)type: 0x06=trans data defined in kcb.h
(2)frmt: 8i~9i 都是0x02
10g block 2k:0x62
4k:0x82
8k:0xa2
16k:0xc2
logfile 0x22 512 bytes
(3)spare1/2_kcbh:
ub1 spare1_kcbhthis field is no longer used (old inc#, now always 0)
ub1 spare2_kcbhthis field is no longer used (old ts#, now always 0)
(4)rdba: 0x0140000a 转换成2进制后它的前10 bit 表示file id 后22bit 表示的block id,可以看出一个tablespace可以有1023 (2^10-1)个datafile ,每个datafile可以有4M 的block,oracle 10G 出现的 big datafile 这里表示的就是block id了 没有file id
Oracle rdba和 dba 说明
http://blog.csdn.net/tianlesoftware/article/details/6529346
(5)scn: scn: 0x0000.0043890e
(6)seq: A sequence number incremented for each change to a block at thesame SCN,A new SCN is allocated if the sequence number wraps.
同一个SCN影响这个block中的行数大于 254 行就会为这个事务分配一个新的SCN,如下面的操作就可能引起同一个SCN但影响的同一个block 中的行超过254行
"delete from table_name"
影响的行数(最大254) 是用从 0x01 到 0xfe 表示的,当这个byte 的数据为 0xff 的时候标志这个 block 坏掉了---> ora-01578
Oracle 坏块 总结
http://www.cndba.cn/Dave/article/1464
(6)Sequence number:
SEQ -> 0 /* non-logged changes - donot advance seq# */
SEQ -> (UB1MAXVAL-1)/* maximumpossible sequence number */
SEQ -> (UB1MAXVAL) /* seq# toindicate a block is corrupt,equal to FF. soft corrupt*/
0xff : Whenpresent it indicates that the block has been marked as corrupt by Oracle.either by the db_block_checking functionality or the equivalent events (10210for data blocks, 10211 for index blocks, and 10212 for cluster blocks) whenmaking a database change, or by the DBMS_REPAIR.FIX_CORRUPT_BLOCKS procedure,or by PMON after an unsuccessful online block recovery attempt while recoveringa failed process, or by RMAN during a BACKUP, COPY or VALIDATE command with theCHECK LOGICAL option. Logical corruptions are normally due to either recoverythrough a NOLOGGING operation, or an Oracle software bug.
(7)flg: as defined in kcbh.h
#define KCBHFNEW 0x01 /* new block - zeroed data area */
#define KCBHFDLC 0x02 /* Delayed Logging Change advance SCN/seq */
#define KCBHFCKV 0x04 /* ChecK Value saved-block xor's to zero */
#define KCBHFTMP 0x08 /* Temporary block */
这是一个可以组合的值 也就是说有为 6 的时候是 2,4 两种情况的组合
Block structure as defined in kcbh.h:
struct kcbh
{ub1 type_kcbh; /* Block type* /
ub1 frmt_kcbh; /* #define KCBH_FRMT8 2 */
ub1 spare1_
cbh;
ub1 spare2_kcbh;
krdba rdba_kcbh; /* relative DBA /
ub4 bas_kcbh; /* base of SCN */
ub2 wrp_kcbh; /* wrap of SCN */
ub1 seq_kcbh; /* sequence # of changes at same scn */
ub1 flg_kcbh;
ub2 chkval_kcbh;
};
该部分 24 bytes
(1) typ : 此处值为1代表 DATA 2 index,改成3了在10.1.0 上引起了ora-600[2032]然后ORA-27101: shared memory realm does not exist。oracle进行查询的时候是根据 obj$表中的情况来判断对象的类型的,不是根据这个typ,也就是说如果有一个表但改变表中block的这个标志位,一样可以查询出数据来,,但dump block 时会出错,ORA-00600: 内部错误代码,自变量: [4555], [0], [], [], [], [], [], []错误中的[0] 就是typ对应的数据,在10G中改变它后update这个block的数据commit可以但rollback的报错
(2)? :见过有其他值 但用编辑器改这个值 在 dump 文件中显示不出来变化
(3)seg/obj: 0xd254
(4)csc : 0x00.43890a The SCN at which the last full cleanout wasperformed on the block
该部分占用24 bytes * itl个数,每个itl 24bytes。
(1) ?: 见过有其他值 但用编辑器改这个值 在 dump 文件中显示不出来变化
(2) itc: ITL 条目的个数 max 255超过会报ORA-02207,ORA-00060ORA-00054 可能是没空间分配itl条目了或它的用引起的.在8i中 INITRANS default为1 , 9.2.0中 INITRANS default为2
(3) flg: indicatesthat the block is on a freelist. Otherwise the flag is -
9i 的ASSM 的情况下这个值为 E,ixora 上说他占用 2 bytes 但我下面的试验和他的结果有一定的出入,我观察到的情况是 : Object id on Block? Y flg: Over: 0x01 ,上面的3项是用同一个 byte 来表示的.
flg: O ver: 0x01 Object id on Block? Y
从我的观察中 dump 出来的文件中 flg verObject id on Block,他们共同占用的这个一个字节 他的规律可以从下面的情况看出,2进制数据 flg ver Object id on Block?
0x00 - 0x00 N
0x01 0 0x00 N
0x02 - 0x01 Y
0x03 0 0x01 Y
0x04 - 0x02 Y
0x05 0 0x02 Y
0x06 - 0x03 Y
0x07 0 0x03 Y
0x08 - 0x04 N
0x09 0 0x04 N
0x0a - 0x05 Y
0x0b 0 0x05 Y
0x0c - 0x06 Y
0x0d 0 0x06 Y
0x0e - 0x07 Y
0x0f 0 0x07 Y
0x10 ... 类似上面的循环了 这种情况在9i上已经改变因为ASSM的出现
(4) fsl : Index tothe first slot on the ITL freelist. ITL TX freelist slot
(5) fnx : 自由列表中下一块的地址 Null if this block is not on a freelist 有数据例如: fnx: 0x1000029
(1) xid : TransactionID (UndoSeg.Slot.Wrap),值可以用select XIDUSN, XIDSLOT,XIDSQN from v$transaction;查到
This is comprised of the rollbacksegment number (2 bytes), the slot number in the transaction table of thatrollback segment (2 bytes), and the number of times use of that transactiontable has wrapped (4 bytes).
(2) uba : Undoaddress (UndoDBA.SeqNo.RecordNo)
The location of the undo for the mostrecent change to this block by this transaction. This is comprised of the DBAof the rollback segment block (4 bytes), the sequence number (2 bytes), and therecord number for the change in that undo block (1 byte), plus 1 unused byte.
(3) Lck Flag: Lck 锁定的row数,这里还用到了下一个 byte 的数据,2 对应的二进制表示为 0010 正好和dump文件中的--U- 吻合.
flag 1 nibble
C = Committed; U = Commit Upper Bound; T = Active at CSC; B = Rollback of thisUBA gives before image of the ITL.
---- = transaction is active, or committed pending cleanout
C--- = transaction has been committed and locks cleaned out
-B-- = this undo record contains the undo for this ITL entry
--U- = transaction committed (maybe long ago); SCN is an upper bound
---T = transaction was still active at block cleanout SCN
Lck 3 nibbles,The number of row-level locks held in the block by thistransaction.
(4) Scn/Fsc : Ifthe transaction has been cleaned out, this is the commit SCN or an upper boundthereof. Otherwise the leading two bytes contain the free space credit for thetransaction - that is, the number of bytes freed in the block by thetransaction
Scn = SCN of commited TX; Fsc = Free space credit (bytes)
该部分占用 14 bytes 从这个flag位置开始是data区,也是下面的行的offset的起始地址
(1) flag : N=pctfreehit(clusters), F=don't put on free list
K=flushable cluster keys. 当然还有别的标记: A ...
(2) ntab : 这block中有几个table的数据 cluster这个就可能大于1
(3) nrow : block 有多少行数据
(1)frre : First free row index entry. -1=you have to addone.
(2) fsbo : FreeSpace Begin offset 出去row dict 后面的可以放数据的空间的起始位置
也可以看成是从这个区域的开始"flag"到最后一个 "row offs"占用的空间
(3) fseo : FreeSpace End offset ( 9.2.0 )参与db_block_checking的计算剩余空间
select 的时候oracle不是简单的根据offset定位row.这个值也是参与了定位row的
(4) avsp : Availablespace in the block (pctfree and pctused) ORA-01578
(5) tosp : Totalavailable space when all TXs commit ( 9.2.0 )参与db_block_checking
(6) offs : 偏移量 用 cluster 的时候可以看出值
(7) nrow : 这个table有多少行数据
(8) row offs: 这行数据相对的起始位置 after delete & commit is 0xffff
该部分为block tail,占用 4bytes
(1) fb :
K = Cluster Key(Flags may change meaning if this is set to show HASH cluster)
C = Cluster table member
H = Head piece of row
D = Deleted row
F = First data piece
L = Last data piece
P = First column continues from previous piece
N = Last column continues in next piece
(2)lb : 和上面的 ITL 的lck相对应表示这行是否被 lock 了
(3)cc : 有几列数据 这里只能表示255列 超过了就会有链接行
(4)length : 这列的数据的长度是多少
0xfa ( 250 bytes ) 其实0xfb,0xfc,0xfd 也同样是250bytes
0xfe fb 00 ( 0xfb 00 表示的251 bytes 0xfe表示row的长度超过了250 bytes)
0xff 表示number 的 null 这也是oracle中null的表现形式排序的时候null最大了
字段的数据超过250字节是就用3bytes来表示字段的长度,因为如果是long类型它的字段再长,它在这个block中的数据的长度不会超过64K 所以最长用3bytes来表示行的长度已经够了.再长就链接行了
(5)data : 'a'
(6)block tail : 改这 block 最后的4 bytes 数据中的任意肯定ora-1578
第 1 byte : 对应开始的 seq
第 2 byte : 对应开始的 type
第3,4byte : 对应开始的scn的末2为 control file 这里是controlseq
三. block坏掉了还可以报如下的错误
ORA-600 (4519) Cache layer block type isincorrect
ORA-600 (4393) Check for Type for Segmentheader with free list
ORA-600 (4136) Check Rollback segment block
ORA-600 (4154) Check Rollback segment block
Ora-600[kcbzpb_1],[d],[kind],[chk] getssignaled when the block got corrupted in memory. The only way it should be badis if a stray store into memory destroyed the header or tail.
d = blocknumber, kind= kind of corruptiondetected,chk = checksum flag
ora-600[3398] and ora-600[3339]
ora-600[3398] is not in oracle 8.
ora-600[3398] means it failed averification check before writing back to disk, so it must be an in-memory corruption.
ora-600[3339] comes with ora-1578 and meanseither disk corruption or in memory corruption after read.
ora-600 [3339] has been removed from 7.2+
From 7.2+ ora-600 [3398] has become ora-600 [3374] with some checks added.
2进制存储格式:
SQL>ALTER SESSION SET EVENTS'10289 trace name context forever, level 1';
SQL> ALTER SESSION SETEVENTS '10289 trace name context off';