`
wsql
  • 浏览: 11787093 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

深入学习data block体系结构

 
阅读更多

环境:

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


㈠ data block 物理结构图

㈡ 一次对block的dump过程

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


㈢ 介绍数据块中包括的3种头信息:

① cache header:数据块是通过data block buffer cache完成读和写操作的,所以它提供了20bytes的Cache Header和4bytes的 Tail给Cache,用来读取和管理

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)

② transaction header:为Transaction层提供的Header信息。它一共占据了48bytes,包括24bytes的控制信息,和一系列的Interested Transaction Slot (ITS)

一共占据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中的空间数

③ data header:剩下的部分都叫Data Area,用来存储用户数据。Data Area也包括data header,和row data及剩余空间。但是Cluster blocks, table blocks, index block的data header,row data结构是不相同的,这里主要介绍table blocks

包括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:
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

㈣ minimum row length

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

㈤ 对于一个没有插入任何row的block来说,并且假设使用了默认的INITRANS,它的大小应该是:

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


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics