Oracle的data block内容研读(转)
Data Block是 Oracle 中存储数据块的最小存储单元,由多个os数据块组成。主要由三个逻辑层组成(通过c语言描绘的结构,如下图一所示):the cache layer,the transaction layer,data layer。如果再细化,data layer又分为很多结构,如table directory,row
DataBlock是Oracle中存储数据块的最小存储单元,由多个os数据块组成。主要由三个逻辑层组成(通过c语言描绘的结构,如下图一所示):the cache layer,the transaction layer,data layer。如果再细化,data layer又分为很多结构,如table directory,row directory,free space,row data等。
所有数据最终都是存储在block中。它也被称为逻辑blocks或是页(pages)。每个操作系统都有自己的block size。而这里的block是Oracle自己的,不同于OS的blocks。可以通过设置DB_BLOCK_SIZE设置Oracle的block为OS的block的几倍,从而减少不必要的I/O。不管block中存放的数据是表、索引还是cluster data,block的结构都是一致。
以下为Oracle block的详细物理结构图
the cache layer:它是block header的第一部分,占用20个bytes。用于检查数据的正确性,即被读的block是否断裂或损坏。它包含如下结构
1.the data block address(DBA)
2.the block type (例如Table/Index, Rollback Segment, Temporary)
3.the block format (8i~9i都是0x02 10.1.0 2k: 0x62 4k:0x82 8k:0xa2 16k:0xc2 (logfile 0x22 512 bytes))
4.a system change number(SCN)used for ordering purposes during recovery
the transaction layer:用户存储数据块里transaction信息的,包含两部分信息
1. 一个是a fixed component ,KTBBH(TRANSACTION FIXED HEADER),包含关于数据块的类型,数据块的最 新cleanout时间,ITL(Interested Transcation List)的数量,空闲列表的链接,还有空闲空间lock。
2.另一个是a variable portion,KTBIT(TRANSACTION VARIABLE HEADER),包含一个进程在一个block里要编辑行所需要的ITLs。默认的包含一个表的数据块只有一个ITL,ITL的多少是通过存储参数INITRANS来设置的,设置较大的值会减少row data的可用空间,这个参数是可以动态修改的,但只影响新的block,对已经存在的block没有作用(可以用imp/exp,move等方法可以让其对存在的block起作用)
The data layer:包含data header结构,KDBH(kernel data block header,是DATA HEADER,占用14bytes),和row data。其中data header包含表的数量(在表索引中,即table directory),数据行的数量,第一个空闲行的条目(在行索引中,即row directory),指向空闲区域的开始和结束的偏移量,可用的空闲空间。数据行是从block的底部开始insert的,伴随insert和delete操作,行数据是随机存储的。
如下图所示:
假设初始化5行数据,每行10bytes大小,按offsets排序是5,4,3,2,1。现在删除2,4行,再insert一行20bytes的数据,在row directory中slot2被使用,但实际的row data存储在row5之上。这个时候再按offsets排序就是2,5,3,1。随着你在数据块上的DML操作的越频繁,这种行的随机性就更强。
下面说下data block的设计,如下图所示
下面,我们就通过SQL语句,结合dump,来查看一下神秘的data block中,到底有些什么信息。
SQL> select dbms_rowid.rowid_relative_fno(rowid) "数据文件",
2 dbms_rowid.rowid_block_number(rowid) "数据块",
3 dbms_rowid.rowid_row_number(rowid) "数据行号"
4 from t_student
5 where id = 111138787
6 ;
数据文件 数据块 数据行号
---------- ---------- ----------
5 80509 25
SQL>
从上面的信息,得到该条记录在datafile 5中的data block 80509中,对应行号为25,通过dump导出该block信息。
[oracle@testserver3 udump]$ sqlplus / as sysdba
SQL*Plus: Release 10.2.0.1.0 - Production on 星期一 12月13 10:36:23 2010
Copyright (c) 1982,2005, Oracle. All rights reserved.
连接到:
Oracle Database10gEnterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options
SQL> alter system dump datafile 5 block 80509;
系统已更改。
至此,该data block已经dump出来了,到user_dump_dest目录下,找得刚生成的文件,打开内容如下:
/oracle/admin/kms/udump/kms_ora_4642.trc
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options
ORACLE_HOME = /oracle/product/10g
System name: Linux
Node name: dbserver
Release: 2.6.18-53.el5
Version: #1 SMP Wed Oct 10 16:34:19 EDT 2007
Machine: x86_64
Instance name: orcl
Redo thread mounted by this instance: 1
Oracle process number: 27
Unix process pid: 4642, image:oracle@dbserver(TNS V1-V3)
*** 2010-12-13 10:36:56.090
*** SERVICE NAME:(SYS$USERS) 2010-12-13 10:36:56.090
*** SESSION ID:(124.665) 2010-12-13 10:36:56.090
Start dump data blocks tsn: 6 file#: 5 minblk 80509 maxblk 80509
buffer tsn: 6 rdba: 0x01413a7d (5/80509)
scn: 0x0000.064c83fdseq: 0x01flg: 0x06tail: 0x83fd0601
【
说明:TAIL用于验证block的完整性的,它是由SCNBase,block type,SCN seq number组成。
83fd0601=83fd(last two bytes of SCN Base)+ 06(type)+ 01(seq)
】
frmt: 0x02 chkval: 0xee80type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x000000001BE18600 to 0x000000001BE1A600
01BE186000000A206 01413A7D 064C83FD 06010000 [....}:A...L.....]
01BE186100000EE8000000001 0001FC23 064C8375 [........#...u.L.]
01BE1862000000000 00320003 01413A0A 00080009 [......2..:A.....]
01BE1863000011CBB 008000F9 001F3675 0000200B [........u6... ..]
01BE18640064C83FD 00090002 00013BAD 0080001C [..L......;......]
01BE186500020370F 00008000 064C01CE 00030004 [.7 .......L.....]
01BE186600000D81F 00801094 00392D71 00008000 [........q-9.....]
01BE18670064B78E0 00000001 00000000 001A0100 [.xK.............]
01BE186800046FFFF 028B01CD 0000028B 1E46001A [..F...........F.]
01BE186901BEB1D17 198F1AC3 17221858 14CF15F8 [........X.".....]
...
...
01BE1A5D0B8D5B8A3 33310BAB 30323339 38333630 [......1393200638]
01BE1A5E002C10230 80018001 80018001 C1028001 [0...............]
01BE1A5F00AC20302 A3D00653 BFB2BEB1 83FD0601 [....S...........]
【
说明:以上信息第一列加粗的是offset(偏移量)
首先来看前20个bytes(上面打下划线的字符),也就是the cache layer,16进制的数据如下:
0000A206 01413A7D 064C83FD 06010000 0000EE80
第一和第二个字节是filler,也就是未被使用(
ub1 spare1_kcbh this field is no longer used (old inc#, now always 0)
ub1 spare2_kcbh this field is no longer used (old ts#, now always 0)
),未被定义(和前面的图有点出入)
第三个字节是frmt,一般是0x02,这里是0xa2,用掩码0x0f与运算可以取出0x02(掩码是为了保护敏感信息)
第四个字节是type,这里是06,代表trans data
第五个到第八个字节是rdba,这里是0x01413A7D
第九个到第十二字节是SCNBase,这里是0x064C83FD
第十三个字节是flg,这里是0x06
(
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两种情况的组合
)
第十四个字节seq,这里是0x01。
(A sequence number incremented for each change to a block at the same 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
Sequence number:
SEQ -> 0 /* non-logged changes - do not advance seq# */
SEQ -> (UB1MAXVAL-1)/* maximum possible sequence number */
SEQ -> (UB1MAXVAL) /* seq# to indicate a block is corrupt,equal to FF.soft corrupt*/
0xff : When present it indicates that the block has been marked as corrupt by Oracle. either by the db_block_checking functionality or the equivalent events (10210 for data blocks, 10211 for index blocks, and 10212 for cluster blocks) when making a database
change, or by the DBMS_REPAIR.FIX_CORRUPT_BLOCKS procedure, or by PMON after an unsuccessful online block recovery attempt while recovering a failed process, or by RMAN during a BACKUP, COPY or VALIDATE command with the CHECK LOGICAL option. Logical corruptions
are normally due to either recovery through a NOLOGGING operation, or an Oracle software bug.)
第十五和第十六字节是SCNWrap,这里是0x0000
第十七和第十八字节是spare3_kcbh,这里未使用
第十九和第二十字节是checksum,这里是0xEE80
相关说明:
buffer tsn: 数据文件对应的 tablespace 的 number ,这只是dump文件中记录的数据而已,block 中是没有记录 tablespace 的 number 的
Rdba:block的相对地址(DBA)
Scn: SCN number
Seq:sequence number incremented for each change made to the block at the same SCN
Flg:flag
Tail:验证block的完整性,通过检查block的开始和结束是否是同一版本
Frmt:block format 通常是0x02
Chkval:如果db_block_checksum=true时,block的核查值
Type:block的类型,如data,index等
到此block的前20bytes都已经解读了,然后再看看紧跟其后的kttbh 的24bytes内容解读
00000001 0001FC23 064C8375 00000000 00320003 01413A0A
第21-24字节,即0x00000001,表示typ ,占4个bytes
(
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的报错)
第25-28字节,即0x0001FC23,表示seg/obj,占4个字节
第29-36字节,即 0x064C8375.00000000,表示csc ,占6个字节(The SCN at which the last full cleanout was performed on the block)
第37字节,即0x00 表示 fsl (Index to the first slot on the ITL freelist. ITL TX freelist slot)
第38字节,即0x32 表示flg
(
indicates that the block is on a freelist. Otherwise the flag is -
9i 的ASSM 的情况下这个值为 E
ixora 上说他占用 2 bytes 但我下面的试验和他的结果有一定的出入
我观察到的情况是 : Object id on Block? Y flg: O ver: 0x01
上面的3项是用同一个 byte 来表示的
flg: O ver: 0x01 Object id on Block? Y
从我的观察中 dump 出来的文件中 flg ver Object 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的出现
)
第39-40字节,即0x0003 表示 itc ,占2个字节。用0x00ff掩码取值,值为3(ITL 条目的个数 max 255超过会报ORA-02207 ORA-00060 ORA-00054 可能是没空间分配itl条目了或它的争用引起的,在8i中 INITRANS default为1 , 9.2.0中 INITRANS default为2)
第41-44字节,即0x01413A0A 表示 (*列表中下一块的地址 Null if this block is not on a freelist)
从44字节以后就是ITL的记录,每个itl所占24bytes
第45-52字节,即0x00080009.00011CBB,表示xid
(
Transaction ID (UndoSeg.Slot.Wrap)
值可以用select XIDUSN, XIDSLOT,XIDSQN from v$transaction;查到
This is comprised of the rollback segment number (2 bytes), the slot number
in the transaction table of that rollback segment (2 bytes), and the number
of times use of that transaction table has wrapped (4 bytes).
)
第53-60字节,即0x008000F9 001F3675,表示uba
(
Undo address (UndoDBA.SeqNo.RecordNo)
The location of the undo for the most recent change to this block by this transaction. This is comprised of the DBA of the rollback segment block (4 bytes), the sequence number (2 bytes), and the record number for the change in that undo block (1 byte), plus
1 unused byte.
)
第63-64字节,即0x200B ,表示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 this UBA 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 this transaction.)
第61-62和65-68字节,即 0x0000.064C83FD 表示Scn/Fsc:
(
If the transaction has been cleaned out, this is the commit SCN or an upper bound thereof. Otherwise the leading two bytes contain the free space credit for the transaction - that is, the number of bytes freed in the block by the transaction
Scn = SCN of commited TX; Fsc = Free space credit (bytes)
)
】
Block header dump: 0x01413a7d
Object id on Block? Y
seg/obj: 0x1fc23 csc: 0x00.64c8375 itc: 3 flg: E typ: 1 - DATA
brn: 0 bdba: 0x1413a0a ver: 0x01 opc: 0
inc: 1 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0009.008.00011cbb 0x008000f9.3675.1f --U- 11 fsc 0x0000.064c83fd
0x02 0x0002.009.00013bad 0x0080001c.370f.20 C--- 0 scn 0x0000.064c01ce
0x03 0x0004.003.0000d81f 0x00801094.2d71.39 C--- 0 scn 0x0000.064b78e0
【
因为这里有三个itls,所有共占用24×3=72bytes空间,再加上20+24+8(这个可能是保留的,具体做什么,不是很清楚?),总124字节
16进制文件如下:
01BE18670 064B78E0 00000001 00000000 001A0100 [.xK.............]
01BE18680 0046FFFF 028B01CD 0000028B 1E46001A [..F...........F.]
01BE18690 1BEB1D17 198F1AC3 17221858 14CF15F8 [........X.".....]
第125字节,即0x00 表示flag
(
N=pctfree hit(clusters), F=don't put on free list
K=flushable cluster keys. 当然还有别的标记: A ...
)
第126字节,即0x1A,表示nrow (block 有多少行数据)
第127字节,即0x01,表示ntab (这block中有几个table的数据 cluster这个就可能大于1)
第128-129字节,即0x0000,表示frre (First free row index entry. -1=you have to add one.)
第130字节,即0x46,表示fsbo
(Free Space Begin offset 出去row dict 后面的可以放数据的空间的起始位置,也可以看成是从这个区域的开始"flag"到最后一个 "row offs"占用的空间)
第135-136字节,即 0x01CD,表示fseo
(
Free Space End offset ( 9.2.0 )参与db_block_checking的计算剩余空间,select 的时候oracle不是简单的根据offset定位row.这个值也是参与了定位row的
)
第139-140字节,即0x028B,表示tosp(Total available space when all TXs commit ( 9.2.0 )参与db_block_checking)
第133-134字节,即0x028B,表示avsp(Available space in the block (pctfree and pctused) ORA-01578)
其中第141-142字节,即0x1E46,表示offsets (偏移量 用 cluster 的时候可以看出值)
第143-144字节,即0x001A,表示nrow(这个table有多少行数据)
】
data_block_dump,data header at 0x1be1867c
===============
tsiz: 0x1f80
hsiz: 0x46
pbl: 0x1be1867c
bdba: 0x01413a7d
76543210
flag=--------
ntab=1
nrow=26
frre=-1
fsbo=0x46
fseo=0x1cd
avsp=0x28b
tosp=0x28b
0xe:pti[0] nrow=26 offs=0
0x12:pri[0] offs=0x1e46
0x14:pri[1] offs=0x1d17
0x16:pri[2] offs=0x1beb
0x18:pri[3] offs=0x1ac3
0x1a:pri[4] offs=0x198f
0x1c:pri[5] offs=0x1858
0x1e:pri[6] offs=0x1722
0x20:pri[7] offs=0x15f8
0x22:pri[8] offs=0x14cf
0x24:pri[9] offs=0x13a5
0x26:pri[10] offs=0x1279
0x28:pri[11] offs=0x1142
0x2a:pri[12] offs=0x1009
0x2c:pri[13] offs=0xf2c
0x2e:pri[14] offs=0xe37
0x30:pri[15] offs=0xd41
0x32:pri[16] offs=0xc0e
0x34:pri[17] offs=0xb10
0x36:pri[18] offs=0xa02
0x38:pri[19] offs=0x8f0
0x3a:pri[20] offs=0x7e8
0x3c:pri[21] offs=0x6e2
0x3e:pri[22] offs=0x5df
0x40:pri[23] offs=0x4d7
0x42:pri[24] offs=0x2d3
0x44:pri[25] offs=0x1cd
block_row_dump:
tab 0, row 0, @0x1e46
tl: 314 fb: --H-FL-- lb: 0x0 cc: 76
col 0: [ 6] c5 02 0c 0e 57 07
col 1: [ 4] c3 05 19 16
col 2: [ 4] d6 a3 b3 bf
col 3: [ 2] c1 02
col 4: [ 4] ba ba d7 e5
col 5: [ 1] 80
col 6: [ 7] 77 b1 08 01 01 01 01
col 7: [ 4] b3 c7 ca d0
col 8: [ 2] c1 02
col 9: *NULL*
col 10: *NULL*
col 11: *NULL*
col 12: *NULL*
col 13: *NULL*
col 14: *NULL*
col 15: [22]
cc ec bd f2 cc fa b3 a7 c9 f1 c9 bd 34 33 23 ce f7 c3 c5 31 30 32
col 16: *NULL*
col 17: *NULL*
col 18: *NULL*
col 19: *NULL*
col 20: [ 7] 78 6e 08 1e 01 01 01
col 21: [ 1] 33
col 22: [ 4] c3 37 24 5b
col 23: [18] 33 34 32 37 30 31 31 39 37 37 30 38 30 31 30 34 32 30
col 24: *NULL*
col 25: [19] 36 32 32 32 30 32 30 34 30 35 30 31 34 35 38 33 39 36 38
col 26: [ 2] c1 02
col 27: *NULL*
col 28: *NULL*
col 29: *NULL*
col 30: *NULL*
col 31: *NULL*
col 32: *NULL*
col 33: *NULL*
col 34: *NULL*
col 35: [ 2] c1 04
col 36: [ 4] 32 30 31 30
col 37: *NULL*
col 38: *NULL*
col 39: *NULL*
col 40: [ 2] c1 02
col 41: *NULL*
col 42: [ 7] 78 6e 0b 08 01 01 01
col 43: [ 4] c7 ef bc be
col 44: *NULL*
col 45: *NULL*
col 46: [ 4] c3 05 19 16
col 47: [ 2] c1 02
col 48: [ 8] 32 30 31 30 d2 b1 c1 b6
col 49: [ 6] ca d0 cf bd c7 f8
col 50: [ 6] cc fa b3 a7 c7 f8
col 51: [ 6] cc ec bd f2 ca d0
col 52: [ 1] 80
col 53: [ 2] c2 03
col 54: [ 1] 80
col 55: [ 1] 80
col 56: [ 7] 78 6e 0b 08 0f 28 3b
col 57: *NULL*
col 58: [13] 6a 69 61 6e 67 73 75 5f 61 64 6d 69 6e
col 59: *NULL*
col 60: [ 4] d0 d5 c3 fb
col 61: [ 7] 78 6e 0c 02 09 37 04
col 62: [ 2] c1 02
col 63: [ 2] c1 03
col 64: [ 2] c1 02
col 65: [ 6] d6 a3 b8 d5 b8 ab
col 66: [11] 31 33 39 33 32 30 30 36 33 38 30
col 67: [ 2] c1 02
col 68: [ 1] 80
col 69: [ 1] 80
col 70: [ 1] 80
col 71: [ 1] 80
col 72: [ 1] 80
col 73: [ 2] c1 02
col 74: [ 3] c2 0a 53
col 75: [ 6] d0 a3 b1 be b2 bf
tab 0, row 1, @0x1d17
。。。
。。。
tab 0,row25, @0x1cd
tl: 262 fb: --H-FL-- lb: 0x1 cc: 76
col 0: [ 6] c5 02 0c 0e 58 58
col 1: [ 4] c3 05 19 16
col 2: [ 6] c0 ee d7 e6 cb b3
col 3: [ 2] c1 02
col 4: [ 4] ba ba d7 e5
col 5: [ 1] 80
col 6: [ 7] 77 c4 05 14 01 01 01
col 7: [ 4] c5 a9 b4 e5
col 8: [ 2] c1 04
col 9: *NULL*
col 10: *NULL*
col 11: *NULL*
col 12: *NULL*
col 13: *NULL*
col 14: *NULL*
col 15: [18] b4 f3 c3 e6 d5 f2 c6 d1 b2 dd b4 e5 37 d7 e9 33 ba c5
col 16: *NULL*
col 17: *NULL*
col 18: *NULL*
col 19: *NULL*
col 20: [ 7] 78 6d 09 01 01 01 01
col 21: [ 1] 33
col 22: [ 4] c3 37 24 5b
col 23: [18] 35 31 30 31 32 31 31 39 39 36 30 35 32 30 31 30 34 58
col 24: *NULL*
col 25: *NULL*
col 26: [ 2] c1 02
col 27: *NULL*
col 28: *NULL*
col 29: *NULL*
col 30: *NULL*
col 31: *NULL*
col 32: *NULL*
col 33: *NULL*
col 34: *NULL*
col 35: [ 2] c1 02
col 36: [ 4] 32 30 31 30
col 37: *NULL*
col 38: *NULL*
col 39: *NULL*
col 40: [ 2] c1 02
col 41: *NULL*
col 42: [ 7] 78 6e 0a 1c 01 01 01
col 43: [ 4] c7 ef bc be
col 44: *NULL*
col 45: *NULL*
col 46: [ 4] c3 05 19 16
col 47: [ 2] c1 03
col 48: [ 5] 30 39 c6 fb 31
col 49: [ 6] b3 c9 b6 bc ca d0
col 50: [ 8] c1 fa c8 aa e6 e4 c7 f8
col 51: [ 6] cb c4 b4 a8 ca a1
col 52: [ 1] 80
col 53: [ 3] c2 02 33
col 54: [ 2] c1 02
col 55: [ 1] 80
col 56: *NULL*
col 57: *NULL*
col 58: *NULL*
col 59: *NULL*
col 60: *NULL*
col 61: *NULL*
col 62: [ 2] c1 02
col 63: [ 2] c1 02
col 64: [ 2] c1 02
col 65: [ 6] c0 ee d4 c6 bb d4
col 66: [11] 31 33 36 37 38 31 36 37 37 37 35
col 67: [ 2] c1 02
col 68: [ 1] 80
col 69: [ 1] 80
col 70: [ 1] 80
col 71: [ 1] 80
col 72: [ 1] 80
col 73: [ 2] c1 02
col 74: [ 3] c2 0a 53
col 75: [ 5] 68 6d 30 30 31
end_of_block_dump
End dump data blocks tsn: 6 file#: 5 minblk 80509 maxblk 80509
内容中,最后一行 tab 0,row25, @0x1cd 为我们查询数据所对应的记录,dbms_rowid.rowid_row_number(rowid)=25。该记录有76列数据,其中类似9~14列的数据为空,非空的数据列对应数据已经过加密。
# 以下是一些比较重要的事务信息,每当一个事务开始时,都要获得一个ITL entry, 否则将会出现ITL 等待。
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0009.008.00011cbb 0x008000f9.3675.1f --U- 11 fsc 0x0000.064c83fd
0x02 0x0002.009.00013bad 0x0080001c.370f.20 C--- 0 scn 0x0000.064c01ce
0x03 0x0004.003.0000d81f 0x00801094.2d71.39 C--- 0 scn 0x0000.064b78e0
@ table directory 记录该块中table rows 的信息,如下所示:
data_block_dump,data header at 0x1be1867c
===============//// tsiz: hsiz: pbl: bdba:在数据文件都是没有存储的
tsiz: 0x1f80//// Total data area size ---8k的block: 8192-20(block
head)-24(Transaction Header)-24*2(一个事务条)-8(我不太清楚的8个字节)-4(block tail)=8072(0x1f80)
hsiz: 0x46//// Data header size 数据块头所占字节数
pbl: 0x1be1867c//// Pointer to buffer holding the block
bdba: 0x01413a7d
76543210
flag=--------
ntab=1 // 这个block有几个table的数据, 除了cluster 以外,一般情况都为1
nrow=26 // 该block 上 rows 的数目
frre=-1
fsbo=0x46
fseo=0x1cd
avsp=0x28b
tosp=0x28b
@ row directroy 记录该块中每一条记录的地址信息,如下所示:
0x12:pri[0] offs=0x1e46
0x14:pri[1] offs=0x1d17
0x16:pri[2] offs=0x1beb
0x18:pri[3] offs=0x1ac3
0x1a:pri[4] offs=0x198f
0x1c:pri[5] offs=0x1858
0x1e:pri[6] offs=0x1722
0x20:pri[7] offs=0x15f8
0x22:pri[8] offs=0x14cf
0x24:pri[9] offs=0x13a5
0x26:pri[10] offs=0x1279
0x28:pri[11] offs=0x1142
0x2a:pri[12] offs=0x1009
0x2c:pri[13] offs=0xf2c
0x2e:pri[14] offs=0xe37
0x30:pri[15] offs=0xd41
0x32:pri[16] offs=0xc0e
0x34:pri[17] offs=0xb10
0x36:pri[18] offs=0xa02
0x38:pri[19] offs=0x8f0
0x3a:pri[20] offs=0x7e8
0x3c:pri[21] offs=0x6e2
0x3e:pri[22] offs=0x5df
0x40:pri[23] offs=0x4d7
0x42:pri[24] offs=0x2d3
0x44:pri[25] offs=0x1cd
最终的记录条数应该和table directory 中的nrow相等。这部分空间一旦被分配,将不可能收回,只能在有新行insert时被重用。
** overhead:在block中,上述的header、table directory和row directory被合称为overhead。
@ row data 记录表中的实际数据。
@free space 该部分主要用于update,insert等操作。 同时ITL entry 也可以在该部分获得。
附录:
一、在data block中free space的使用与优化:当数据被delete或update时,可能引起block产生free space,对此:①如果有insert语句与相应释放block space的语句在同一个transaction中,则insert可以使用刚刚释放的block space;②如果insert语句与相应的释放block space的语句不在同一个transaction中,则释放的block space只有在事务被commit之后才能被使用。Oracle当发生以下两种情况会进行free space的合并:insert或update操作视图使用一个有足够free space的block;free space存在大量碎片,无法进行数据的insert等。
二、row的链接与迁移:当一条记录row的数据太大时,可能无法放在一个block中,这种情况下Oracle往往会使用chain(链接)的方法;此外,当one row被update后,数据量增大,当前的block已经不能完全容纳时,Oracle会把该row数据整个迁移(migrates)到其他的数据块中,但在原来row的位置上保存一个指针,链接到新的地址上,大量的迁移、链接将会降低DB的I/O性能。