block基础

block基础2
===========================================================
block基础2

• 现在然我们研究一下block的内容,Oracle的block的内容分为:header,free space和data。

• Free space
• Free space和其他两部分的区别就是free space没有存放任何数据,而header和data是已经被用来存放数据了(其中header用户来存放block的管理数据,而data用来存放应用数据)。对于一个刚刚分配的新block,只有header和free space两部分。从位置上,最上面是header,然后是free space,最后是data。header是从上往下用空间,data是从下往上用空间,free space夹在为二者提供空间。
• 严格上将,block header有一点点数据是放在block的最末位的地方的,叫做tail,这是用来做block consistency checking的,这个tail的作用是用来检测这个块是不是分裂的块,具体的让我们留到backup的章节介绍。

• 我们这样说:free space是block里面用来存放数据的空闲空间,在oracle中这部分block是被分为两部分的:一部分free space用来add data,一部分free space用来expend data。Add data就是我们往block里面insert数据,expend data就是我们做update操作,让我解释一下为什么要把free space分成两部分:
• 试想一个这样的情景,假如一个这样的表里的一个block已经满了,这个block上的某一行内容是”Oracle is beast if you use incorrectly” (只有一行是这个内容)
SQL> desc test
Name Null? Type
----------------------------------------- -------- ----------------------------
C1 VARCHAR2(100)

• 这时候你做了一个这样的update:
update test set c1='Oracle is beast if you use incorrectly but it will be gentle if you really know it‘ where c1=‘Oracle is beast if you use incorrectly’;
1 row updated.

• 现在这一行变大了,但是我们说过block是满的,Oracle会如何处理呢?这种情况下Oracle会把这一行移到其他有足够空间的block,并在原行的位置留一个标记,指向新的行地址。这叫做row migration,很明显,读一个migrated row需要两次read,而不是一次,从而影响性能。为了解决这个问题,Oracle允许通过设置一个叫pctfree的参数,为block保留一部分的空间。假如你设置pctfree为20,这表明整个block的20%是用来expend data,当你向这个block insert数据的时候,你最多可以使用block 80%的空间(实际上由于header的存在,你不可能用到80%),剩下的部分与留下来用来扩展现有的行。很明显,pctfree的大小是和你对数据的update的方式相关的,对于read only的数据,你可以设置pctfree为0。

• 对于行迁移的一个例子如下:
SQL> create table t1 (x int, y varchar2(200)) pctfree 0;
Table created.
SQL> begin
2 for i in 1 .. 1000
3 loop
4 insert into t1 values (i, 'Oracle is beast if you use incorrectly');
5 end loop;
6 commit;
7 end;
8 /

PL/SQL procedure successfully completed.

SQL> select extent_id, blocks, block_id from dba_extents where segment_name='T1' and owner='LII';
EXTENT_ID BLOCKS BLOCK_ID
---------- ---------- ----------
0 8 9
1 8 17

SQL> analyze table t1 compute statistics;
Table analyzed.

SQL> col table_name format a5
SQL> select table_name,num_rows,CHAIN_CNT from user_tables where table_name='T1';
TABLE NUM_ROWS CHAIN_CNT
----- ---------- ----------
T1 1000 0

SQL> update t1 set y='Oracle is beast if you use incorrectly but it will be gentle if you really kno
w it' where x=1;
1 row updated.

SQL> commit;
Commit complete.

SQL> analyze table t1 compute statistics;
Table analyzed.

SQL> select table_name,num_rows,CHAIN_CNT from user_tables where table_name='T1';
TABLE NUM_ROWS CHAIN_CNT
----- ---------- ----------
T1 1000 1

• Header
• Block header是位于block头部的,用来存储block的描述信息的部分,这部分不存储任何用户数据,但对block的管理、使用是非常关键的。
• 简单的说,block header可以分为两部分:
1. 第一部分是定长部分,记录了block type (table, index…实际上就是所在的segment type),block的地址。
2. 第二部分是变长的部分,里面的信息包括row directory---记录了这个block里的行的信息,包括行地址。
Oracle9i database concept里关于row directory有这样的一段描述很有趣:
(原文见http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96524/c03block.htm#2595)
After the space has been allocated in the row directory of a data block’s overhead, this space is not reclaimed when the row is deleted. Therefore, a block that is currently empty but had up to 50 rows at one time continues to’ have 100 bytes allocated in the header for the row directory. Oracle reuses this space only when new rows are inserted in the block.
这其实是主要出于performance的考虑,相对于每次delete之后都更新一次block header,oracle更倾向于较集中的处理并重用空间。
变长部分更重要的部分是ITL:Interested Transaction List,这部分影响block的concurrency能力, ITL实际就是放在block header的一段数据,称为ITL slot。每个slot都是这个block上的transaction的入口,也就是说,如果这个block上有10个ITL slot,那么在这个block在同一时刻最多允许的transaction数量是10。

ITL的个数由存储参数inittrans和maxtrans,一般在create table (index)时设置, 相信你已经猜到了, inittrans就在一个初始的block上的slot个数, maxtrans则是这个block上最大的slot个数,默认设置( inittrans =1, maxtrans =255)基本上对大多数情况都是适用的。由于ITL slot本身占用空间并且需要管理,所以盲目增大inittrans并不可取,默认的maxtrans =255已经很大了,很少有应用会在同一时刻在单个block上产生255个事务。

一般来说,默认的ITL的设置是比较合理的,但是不要忘记,在Oracle里面没有万能的设置,在我们下面case里的默认的inittrans =1, maxtrans =255是有问题的:

SQL> create table t1 (x int, y varchar2(200)) pctfree 0;
Table created.

SQL> select INI_TRANS,MAX_TRANS from user_tables where table_name='T1';
INI_TRANS MAX_TRANS
---------- ----------
1 255

SQL> begin
2 for i in 1 .. 1000
3 loop
4 insert into t1 values (i, 'Oracle is beast if you use incorrectly');
5 end loop;
6 commit;
7 end;
8 /

PL/SQL procedure successfully completed.

SQL> select file_id ,extent_id, blocks, block_id from dba_extents where segment_name='T1' and owner
='LII';
FILE_ID EXTENT_ID BLOCKS BLOCK_ID
---------- ---------- ---------- ----------
5 0 8 9
5 1 8 17

SQL> select rowid from t1 where x=1;
ROWID
------------------
AAABjfAAFAAAAAMAAA

SQL> select rowid from t1 where x=2;
ROWID
------------------
AAABjfAAFAAAAAMAAB

SQL> select rowid from t1 where x=3;
ROWID
------------------
AAABjfAAFAAAAAMAAC

SQL> SELECT dbms_rowid.rowid_block_number('AAABjfAAFAAAAAMAAA') from dual;
DBMS_ROWID.ROWID_BLOCK_NUMBER('AAABJFAAFAAAAAMAAA')
---------------------------------------------------
12

SQL> SELECT dbms_rowid.rowid_block_number('AAABjfAAFAAAAAMAAB') from dual;
DBMS_ROWID.ROWID_BLOCK_NUMBER('AAABJFAAFAAAAAMAAB')
---------------------------------------------------
12

SQL> SELECT dbms_rowid.rowid_block_number('AAABjfAAFAAAAAMAAC') from dual;
DBMS_ROWID.ROWID_BLOCK_NUMBER('AAABJFAAFAAAAAMAAC')
---------------------------------------------------
12

SQL> alter system dump datafile 5 block 12;
System altered.

##########以不同的session logon
session 1:
SQL> update t1 set x=1 where x=1;
1 row updated.
session 2:
SQL> update t1 set x=2 where x=2;
1 row updated.
SQL> update t1 set x=3 where x=3;
(处于等待)
大家请考虑一下,是什么原因?

fusnow 发表于:2006.09.20 17:43 ::分类: ( oracle相关 ) ::阅读:(170次) :: 评论 (1)
comment_icon1.gif re: block基础2 [回复]

关注你的这个帖子

我现在遇到这个问题,我在批量注册用户,每次开100个用户,每次都要去更新号段表,把当前值加1,单个批开没问题,但在批开的时候我还进行单个用户的注册,结果造成两边的操作都不能进行了,是不是我加大这个inittrans就可以呢?

ref: http://fusnow.itpub.net/index.php

[@more@]

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7916042/viewspace-911234/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/7916042/viewspace-911234/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值