环境:
SQL> select * from v$version where rownum=1; BANNER ---------------------------------------------------------------- Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod SQL> !uname -a Linux localhost.localdomain 2.6.18-308.el5xen #1 SMP Fri Jan 27 17:59:00 EST 2012 i686 i686 i386 GNU/Linux
hr@ORCL> create table think(a varchar2(10)); Table created. hr@ORCL> insert into think values('a'); 1 row created. hr@ORCL> commit; Commit complete. hr@ORCL> execute show_space('think','auto'); Total Blocks............................8 Total Bytes.............................65536 Unused Blocks...........................0 Unused Bytes............................0 Last Used Ext FileId....................4 Last Used Ext BlockId...................401 Last Used Block.........................8 PL/SQL procedure successfully completed. sys@ORCL> alter system dump datafile 4 block 404; System altered.
trc如下:
Start dump data blocks tsn: 4 file#: 4 minblk 407 maxblk 407 buffer tsn: 4 rdba: 0x01000197 (4/407) scn: 0x0000.000a2707 seq: 0x03 flg: 0x02 tail: 0x27070603 frmt: 0x02 chkval: 0x0000 type: 0x06=trans data Hex dump of block: st=0, typ_found=1 Dump of memory from 0x0E1BA400 to 0x0E1BC400 E1BA400 0000A206 01000197 000A2707 02030000 [.........'......] E1BA410 00000000 00000001 0000CD8A 000A26FE [.............&..] E1BA420 00000000 00320002 01000191 00050001 [......2.........] E1BA430 00000100 0080000F 002300AE 00002001 [..........#.. ..] E1BA440 000A2707 00000000 00000000 00000000 [.'..............] E1BA450 00000000 00000000 00000000 00000000 [................] E1BA460 00000000 00010100 0014FFFF 1F7B1F93 [..............{.] E1BA470 00001F7B 1F930001 00000000 00000000 [{...............] E1BA480 00000000 00000000 00000000 00000000 [................] Repeat 502 times E1BC3F0 00000000 2C000000 61010101 27070603 [.......,...a...'] Block header dump: 0x01000197 Object id on Block? Y seg/obj: 0xcd8a csc: 0x00.a26fe itc: 2 flg: E typ: 1 - DATA brn: 0 bdba: 0x1000191 ver: 0x01 opc: 0 inc: 0 exflg: 0 Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x0001.005.00000100 0x0080000f.00ae.23 --U- 1 fsc 0x0000.000a2707 0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000 data_block_dump,data header at 0xe1ba464 =============== tsiz: 0x1f98 hsiz: 0x14 pbl: 0x0e1ba464 bdba: 0x01000197 76543210 flag=-------- ntab=1 nrow=1 frre=-1 fsbo=0x14 fseo=0x1f93 avsp=0x1f7b tosp=0x1f7b 0xe:pti[0] nrow=1 offs=0 0x12:pri[0] offs=0x1f93 block_row_dump: tab 0, row 0, @0x1f93 tl: 5 fb: --H-FL-- lb: 0x1 cc: 1 col 0: [ 1] 61 end_of_block_dump End dump data blocks tsn: 4 file#: 4 minblk 407 maxblk 407
trc部分引用:
buffer tsn: 4 rdba: 0x01000197 (4/407) scn: 0x0000.000a2707 seq: 0x03 flg: 0x02 tail: 0x27070603 frmt: 0x02 chkval: 0x0000 type: 0x06=trans data
trc部分解释:
trc部分解释:
rdba:包括Tablespace 所在数据文件的相对文件号file#=4, 和数据块的block_id=407
scn:占用6bytes,最后变化的scn。包括2bytes的高位字节(SCN wrap),和4bytes的低位字节(SCN base)
Sequence:占用1byte,用途不明确,可能是辅助SCN的变化
Flag:占用1byte,flag 表示标记,如删除标记等
Format:占用1byte,应该是用来区分版本。Oracle 8之前值为1,之后为2
Checksum:占用2byte,跟db_block_checksum 参数有关系
下面比较一下db_block_checking and db_block_checksum:
SQL> show parameter db_block_checksum NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_block_checksum string TRUE SQL> show parameter db_block_checking NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ db_block_checking string FALSE
db_block_checking:对逻辑坏块(块头和块身是否一致)的校验、开了会损耗10%~15%的性能、即使为false、也对system表空间进行检查
db_block_checksum:对物理坏块的校验
Block type: 占用1byte,经常用到的有,1=undo segment header block; 2=undo data block; 5= data segment header block; 6=data block
几个其它的type:
0x20=FIRST LEVEL BITMAP BLOCK
0x21=SECOND LEVEL BITMAP BLOCK
用于ASSM的位图
0x23=PAGETABLE SEGMENT HEADER
ASSM段头
记录高高水位和低高水位,还有1,2 level的BMB位置以及可能存在的3 level BMB位置
Tail:包括了SCN中SCN base的低位(low-order)2bytes,然后是block type,还有Sequence number。每当block 被读的时候,都要检查Tail与 block header 是否一致, 保证了这个block不是损坏的(corrupted)
一共占据48bytes,包括24bytes的控制信息,和一系列的Interested Transaction Slot (ITS)。这些ITS组合在一起称为Interested Transaction List (ITL)。初始的ITL slot
数量由 INITRANS 决定(index branch block 只有1个slot)。如果有足够的剩余空间,oracle会根据需要动态的分配这些slot,直到受到空间限制或者达到了MAXTRANS
trc部分引用:
Block header dump: 0x01000197 Object id on Block? Y seg/obj: 0xcd8a csc: 0x00.a26fe itc: 2 flg: E typ: 1 - DATA brn: 0 bdba: 0x1000191 ver: 0x01 opc: 0 inc: 0 exflg: 0 Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x0001.005.00000100 0x0080000f.00ae.23 --U- 1 fsc 0x0000.000a2707 0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
trc部分解释:
Object number(seg/obj): 占用4bytes,指在OBJ$中记录的segment 的 object number(0xcd8a=52618)
Cleanout SCN(csc):占用6bytes,最后一次 full cleanout 的scn
ITL count(itc): 占用1byte,ITL 的slot数量
Flag:占用2bytes。O表示这个block在freelist 上。否则flag为"-"
对于ASSM段,flag始终是E,由于ASSM自动管理freelists,extent的可用与否在1 level BMB中定义
Block type: 占用1byte。1=data; 2=index
ITL freelist slot(fsl): 占用1byte。Index to the first slot on the ITL freelist
Next freelist block(fnx):占用4byte。Segment freelist中下一个block的RDBA
Version:1 byte
每个ITL entry包括以下的内容:
xid:含xidusn、xidslot、xidsqn
uba:包括rollback segment block的DBA,sequence number等
flag:
---- = 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
locks:行级锁
SCN or free space credit:6bytes. 如果这个事务已经clean out,这个值就是SCN;否则,前两个字节表示由这个事务释放的此block中的空间数
包括14bytes的data header,4bytes/table的table dictionary,2bytes/row的row dictionary,即每增加一条row,row dictionary就多出2bytes用来记载该row,可以通过下面的hsiz反映出来。Table Directory主要用于cluster block,可以共享给多个table;对于table block,Table Directory总为1。
trc部分引用:
data_block_dump,data header at 0xe1ba464 =============== tsiz: 0x1f98 hsiz: 0x14 pbl: 0x0e1ba464 bdba: 0x01000197 76543210 flag=-------- ntab=1 nrow=1 frre=-1 fsbo=0x14 fseo=0x1f93 avsp=0x1f7b tosp=0x1f7b 0xe:pti[0] nrow=1 offs=0 0x12:pri[0] offs=0x1f93 block_row_dump: tab 0, row 0, @0x1f93 tl: 5 fb: --H-FL-- lb: 0x1 cc: 1 col 0: [ 1] 61 end_of_block_dump End dump data blocks tsn: 4 file#: 4 minblk 407 maxblk 407
trc部分解释:
tsiz:total data area size
hsiz:data header size (14+ntabs*4 + nrows*2)
pbl:pointer to buffer holding the block
bdba:block dba / rdba
flag:n=pctfree hit (clusters),f=don't put on freelist, k=flushable cluster keys
ntab:number of tables (>1 so this is a cluster)
nrow:number of rows
fsbo:free space begin offset
fseo:free space end offset
avsp:available space in the block
tosp:total available space when all transactions commit
推论:数据的存储是从块的底部开始的
tab 0, row 0, @0x1f93:3bytes row header
tl: 5 fb: --H-FL-- lb: 0x1 cc: 1 =>lb: 0x1 表示transaction 0x1,cc 表示column的个数,每个row有3字节的row header
col 0: [ 1] 61 => column length(1 byte if length<250; otherwise 3 bytes) and values
其中:
fb =>Flag Byte(KCHDFLPN): 行类型
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
lb => ITL number
cc => column count
Oracle确实有Minimun row length的要求,即5 bytes的实际数据。如果加上3 bytes的row header, 和在block hader 中占据的2 bytes的row directory entry ,还有1byte的
column长度,应该一共是11 bytes。所以,一个block中最多包括 db_block_size/11 条rows
db_block_size- (cache header+ transaction header +data header + Tail + table dictionary*ntab + row dictionary*row )=8192 - ( 20+48+14+4+4 +0)=8192 - 90 =8102 bytes
⑴ transaction slots的作用是什么,我觉得,如果一个transaction对该数据块中的row进行了更改或增加,删除,应该直接在该row中置上该transaction的sid,因为其它的transaction都是直接寻找到每一个row的数据的,他们要知道该row是被哪一个transaction所控制,而transaction slots是针对整个数据块的,怎么能够反映每一row的具体锁定信息?
答:是在每个row上标记了transaction 的Itl。如果你通过3个不同的session 对同一个block操作,并且都未提交时:
---------------session 1---------------- SQL> insert into t values(1); 1 row created. ---------------session 2---------------- SQL> insert into t values(1); 1 row created. ---------------session 3---------------- SQL> insert into t values(3); 1 row created. Start dump data blocks tsn: 8 file#: 3 minblk 842 maxblk 842 buffer tsn: 8 rdba: 0x00c0034a (3/842) scn: 0x0000.006d3763 seq: 0x01 flg: 0x00 tail: 0x37630601 frmt: 0x02 chkval: 0x0000 type: 0x06=trans data Block header dump: 0x00c0034a Object id on Block? Y seg/obj: 0x80a9 csc: 0x00.6d36e9 itc: 3 flg: O typ: 1 - DATA fsl: 0 fnx: 0x0 ver: 0x01 Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x0001.00b.00001001 0x00800026.011b.02 ---- 1 fsc 0x0000.00000000 0x02 0x0006.01d.00001047 0x008028c2.00c8.3b ---- 1 fsc 0x0000.00000000 0x03 0x000a.028.0000104c 0x008001bc.00d5.02 ---- 1 fsc 0x0000.00000000 Flags为 ---- = transaction is active, or committed pending cleanout data_block_dump,data header at 0x4791074 =============== tsiz: 0x1f88 hsiz: 0x18 pbl: 0x04791074 bdba: 0x00c0034a 76543210 flag=-------- ntab=1 nrow=3 frre=-1 fsbo=0x18 fseo=0x1f70 avsp=0x1f55 tosp=0x1f55 0xeti[0] nrow=3 offs=0 0x12ri[0] offs=0x1f7c 0x14ri[1] offs=0x1f76 0x16ri[2] offs=0x1f70 block_row_dump: tab 0, row 0, @0x1f7c tl: 6 fb: --H-FL-- lb: 0x1 cc: 1--->lb: 0x1 就是 Itl col 0: [ 2] c1 02 tab 0, row 1, @0x1f76 tl: 6 fb: --H-FL-- lb: 0x2 cc: 1--->lb: 0x2 就是 Itl col 0: [ 2] c1 03 tab 0, row 2, @0x1f70 tl: 6 fb: --H-FL-- lb: 0x3 cc: 1--->lb: 0x3 就是 Itl col 0: [ 2] c1 04 end_of_block_dump End dump data blocks tsn: 8 file#: 3 minblk 842 maxblk 842 3个session都提交后: Start dump data blocks tsn: 8 file#: 3 minblk 842 maxblk 842 buffer tsn: 8 rdba: 0x00c0034a (3/842) scn: 0x0000.006d3817 seq: 0x01 flg: 0x02 tail: 0x38170601 frmt: 0x02 chkval: 0x0000 type: 0x06=trans data Block header dump: 0x00c0034a Object id on Block? Y seg/obj: 0x80a9 csc: 0x00.6d36e9 itc: 3 flg: O typ: 1 - DATA fsl: 0 fnx: 0x0 ver: 0x01 Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x0001.00b.00001001 0x00800026.011b.02 --U- 1 fsc 0x0000.006d3817 0x02 0x0006.01d.00001047 0x008028c2.00c8.3b --U- 1 fsc 0x0000.006d3802 0x03 0x000a.028.0000104c 0x008001bc.00d5.02 --U- 1 fsc 0x0000.006d3800 flag --U- 表示事务已经提交 data_block_dump,data header at 0x4791074 =============== tsiz: 0x1f88 hsiz: 0x18 pbl: 0x04791074 bdba: 0x00c0034a 76543210 flag=-------- ntab=1 nrow=3 frre=-1 fsbo=0x18 fseo=0x1f70 avsp=0x1f55 tosp=0x1f55 0xeti[0] nrow=3 offs=0 0x12ri[0] offs=0x1f7c 0x14ri[1] offs=0x1f76 0x16ri[2] offs=0x1f70 block_row_dump: tab 0, row 0, @0x1f7c tl: 6 fb: --H-FL-- lb: 0x1 cc: 1 col 0: [ 2] c1 02 tab 0, row 1, @0x1f76 tl: 6 fb: --H-FL-- lb: 0x2 cc: 1 col 0: [ 2] c1 03 tab 0, row 2, @0x1f70 tl: 6 fb: --H-FL-- lb: 0x3 cc: 1 col 0: [ 2] c1 04 end_of_block_dump End dump data blocks tsn: 8 file#: 3 minblk 842 maxblk 842
⑵ 不应该是5个字节的实际数据 这11个字节是3 bytes的row header,block hader 中占据的2 bytes,还有6字节的rowid,如果没记错的话 如果发生行迁移的row就是这样的结构?
答:ROWID只是个逻辑概念,并不存储在data block中。只是在index block中存储6位的rowid,指向索引的实际数据。oracle 8开始 rowid 是 10bytes,原来是6bytes
⑶ 3个字节的row header包含什么内容?
tl: 5 fb: --H-FL-- lb: 0x1 cc: 1 =>一共多长,状态标记,被哪个transaction 用到,有几个列,这些信息应该都存在row header 中
⑷ 请问在块的什么地方标记出------被修改块已经不在内存中已被写到磁盘上?是如何标记的?
答:脏块会放置在data buffer 中的所谓dirty list上等待被写入磁盘。写入后所在的buffer 则被放置到LRU链上,等待被重用
⑸ 一个row的基本体系结构大概是什么样子的?
答:row 在block中的起始位置,就是存储在block row slots中的指针数值,就是2bytes的row dict entry;2bytes可以表示64k空间 因此一个bock最大为64k
在row上要包括一些额外信息,就是3个字节的row header: 如
fb: --H-FL-- lb: 0x1 cc: 2
其中一个字节表示行锁信息,itl标记,1bytes表示最多支持255个itl
其中一个字节表示该行在这个block中有几列,因为关于列类型,表列数目,列顺序都一样且冗余,因此没有必要存储在block中,oracle从数据字典获得这些信息;
1bytes表示该行在该block中的数目,正好表示当一行超过255列的时候会自动发生行迁移,将多余行存储在其他block上。
另外一个bytes就是表示该row的状态信息,如是全部存储在该block中,还是发生迁移链接 etc
然后紧跟的是第n列的长度,第n列的内容 ....
block_row_dump:
tab 0, row 0, @0x1fb1 -8113
tl: 7 fb: --H-FL-- lb: 0x1 cc: 2 ---- tl = total length;cc = column count;每个row有3字节的row header;
col 0: [ 1] 64 ----一个字节记录column长度(如果长度小于250,否则用3个字节)。接着是colomn数据。
col 1: [ 1] 65
end_of_block_dump
如果发生行迁移/链接的话,自然要在row上标记row piece的位置,6bytes FFFBBBBBBRRR