1.数据块头:包含了此数据块的概要信息,如块地址(block address)及数据块所属的段的类型。
2.表目录区:如果一张表在此数据块中存储了数据行,那么这张表的信息将被记录在数据块的表目录区中。
3.行目录区:此区域包含数据块中存储的数据行的信息。
4.可用空间区:在插入新数据行,或在更新数据行需要空间时,将使用此区域。
5.行数据区:包含表和索引的实际数据。一个数据行可以跨多个数据块。
Dump脚本,dump的文件在D:\oracle\product\10.2.0\admin\ordb10\udump下面 alter session set tracefile_identifier = 'Look_For_Me'; create table test(name varchar2(10)); insert into test values('中国'); insert into test values('美国'); commit; select rowid, dbms_rowid.rowid_object(rowid) object_id, dbms_rowid.rowid_relative_fno(rowid) file_id, dbms_rowid.rowid_block_number(rowid) block_id, dbms_rowid.rowid_row_number(rowid) num from test; alter system dump datafile 6 block 124232; Show_space创建脚本:http://blog.csdn.net/guogang83/article/details/7963299
dump出来的文件如下
seg/obj: 0x180a2 csc: 0x95a.e56f14c6 itc: 2 flg: E typ: 1 - DATA brn: 0 bdba: 0x181e541 ver: 0x01 opc: 0 inc: 0 exflg: 0 Itl Xid Uba Flag Lck Scn/Fsc 0x01 0x0002.002.000072bb 0x0081fa06.1e1c.26 --U- 2 fsc 0x0000.e56f14ce 0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000 。。。。。。。。。。。省略。。。。。。。。。。。 0x14:pri[1] offs=0x1f88 block_row_dump: tab 0, row 0, @0x1f90 tl: 8 fb: --H-FL-- lb: 0x1 cc: 1 col 0: [ 4] d6 d0 b9 fa tab 0, row 1, @0x1f88 tl: 8 fb: --H-FL-- lb: 0x1 cc: 1 col 0: [ 4] c3 c0 b9 fa end_of_block_dump
Block内容解析--The Transaction Header
一共占据48bytes,包括24bytes的控制信息,和一系列的Interested Transaction Slot (ITS)。这些ITS组合在一起称为Interested Transaction List (ITL)。初始的ITL slot 数量由 INITRANS 决定(index branch block 只有1个slot)。如果有足够的剩余空间,oracle会根据需要动态的分配这些slot,直到受到空间限制或者达到了MAXTRANS。 Object number(seg/obj): 占用4bytes,指在OBJ$中记录的segment 的 object number(0x806d=32877) Cleanout SCN(csc): 占用6bytes,最后一次 full cleanout 的scn ITL count(itc): 占用1byte,ITL 的slot数量。 Flag: 占用2bytes。O表示这个block在freelist 上。否则flag为”-” 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 Unused: 4bytes,用来前后兼容。
1. block中所有的含义,请参考http://blog.csdn.net/guogang83/article/details/8640555
2.二进制、八进制、十进制、十六进制的相互转换请参考http://blog.csdn.net/guogang83/article/details/8002014
如:select pkg_number_trans.f_hex_to_dec(‘1b5’) from dual;--十六进制转换为十进制
Block内容解析-- Data Area
包括14bytes的data header,4bytes/table的table dictionary,2bytes/row的row dictionary。table dictionary主要用于cluster block中,只不过table block中的table dictionary只有一个table。
select chr(to_number('d6d0','xxxx')) from dual;--中
select chr(to_number('b9fa','xxxx')) from dual;--国
1.不同的数据类型解析规则不一样,想要知道更多的数据类型解析,请参考http://blog.csdn.net/guogang83/article/details/8010105
Oracle实现行锁
insert into test values('韩国'); insert into test values('朝鲜'); insert into test values('越南'); commit; alter system dump datafile 6 block 124232; 重新开一个session: select * from test where name='韩国' for update; 重新开一个session: select * from test where name='韩国' for update;
将block dump出来
Block参数PCTFREE、PCTUSED
•PCTFREE:为一个块保留的空间百分比,表示数据块在什么情况下可以被insert,默认是10,表示当数据块的可用空间低于10%后,就不可以被insert了,只能被用于update;即:当使用一个block时,在达到pctfree之前,该block是一直可以被插入的,这个时候处在上升期。
•PCTUSED:是指当块里的数据低于多少百分比时,又可以重新被insert,一般默认是40,即40%,即:当数据低于40%时,又可以写入新的数据,这个时候处在下降期。
•注意:10g以后PCTUSED已经过时。
看懂下面例子,各参数意义
create table TEST(ID NUMBER ) tablespace DFWMS pctfree 10 initrans 1 maxtrans 255 storage ( initial 64 minextents 1 maxextents unlimited ); 建表时的参数含义?
行迁移
原本存储在一个数据块内的数据行,因为更新操作导致长度增长,而所在数据块的可用空间也不能容纳增长后的数据行。在这种情况下,oracle将此行数据迁移到新的数据块中,oracle在被迁移数据行原本所在位置保存一个指向新数据块的指针。被迁移数据行的rowid保持不变。当数据行发生链接或迁移时,对其访问将会造成I/O性能降低,因为oracle为获取这些数据行的数据时,必须访问更多的数据块。
要想构造出行迁移,我们要有点特殊的手段,需要尽量让数据块满,只要把pctfree设置小一点就可以了。插入一些数据后,找到一个块满的,然后做修改,由于块中已没有空间支持行链接,则发生行迁移,是整行发生迁移。 drop table t purge; select * from t; create table t (a varchar2(4000), b varchar2(4000), c varchar2(4000)) pctfree 2; begin for i in 1.. 1000 loop insert into t values(i,i,i); end loop; commit; end; select count(1),block_id from (select rowid,a, dbms_rowid.rowid_object(rowid) object_id, dbms_rowid.rowid_relative_fno(rowid) file_id, dbms_rowid.rowid_block_number(rowid) block_id, dbms_rowid.rowid_row_number(rowid) num from t )group by block_id; select max(a) max_a,min(a) min_a from(select rowid,a, dbms_rowid.rowid_object(rowid) object_id, dbms_rowid.rowid_relative_fno(rowid) file_id, dbms_rowid.rowid_block_number(rowid) block_id, dbms_rowid.rowid_row_number(rowid) num from t) where block_id=1471; update t set b=lpad('2', 4000, '2'),c=lpad('2', 4000, '2') where to_number(a) >484 and to_number(a) <950; alter system dump datafile 4 block 1471;
注:4和1471是上述脚本查来的
dump
trace的文件:黄色部分就是行迁移 tl: 9 fb: --H----- lb: 0x2 cc: 0nrid: 0x010005f0.0tab 0, row 10, @0x1e89tl: 9 fb: --H----- lb: 0x2 cc: 0nrid: 0x010005f7.0tab 0, row 11, @0x1e80tl: 9 fb: --H----- lb: 0x2 cc: 0nrid: 0x010005f1.0tab 0, row 12, @0x1e77tl: 9 fb: --H----- lb: 0x2 cc: 0nrid: 0x010005f3.0tab 0, row 13, @0x1e43tl: 52 fb: --H-F--N lb: 0x2 cc: 2nrid: 0x010005f4.0col 0: [ 3] 34 39 38col 1: [38] 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 转换nrid: select dbms_utility.DATA_BLOCK_ADDRESS_FILE(to_number('018047bc', 'xxxxxxxxxx')) file#, dbms_utility.DATA_BLOCK_ADDRESS_BLOCK(to_number('018047bc', 'xxxxxxxxxx')) block# from dual;
行链接
当一行数据被插入时一个数据块就无法容纳,在这种情况下oracle将这行数据存储在段内的一个数据块链中。在插入数据量大的行时常会发生行链接(row chaining)。例如一个包含数据类型为long或long raw列的数据行,此时行链接不可避免。
create table t (a varchar2(4000), b varchar2(4000), c varchar2(4000)); insert into t values (lpad('1', 4000, '1'), lpad('2', 4000, '2'), lpad('3', 4000, '3')); commit; select rowid, dbms_rowid.rowid_object(rowid) object_id, dbms_rowid.rowid_relative_fno(rowid) file_id, dbms_rowid.rowid_block_number(rowid) block_id, dbms_rowid.rowid_row_number(rowid) num from t; ROWID OBJECT_ID FILE_ID BLOCK_ID NUM------------------ ---------- ---------- ---------- ----------AAAXUTAAGAAAEe9AAA 95507 6 18365 0 alter system dump datafile 6 block 18365;
dump
System altered data_block_dump,data header at 0xa768464===============tsiz: 0x1f98hsiz: 0x14pbl: 0x0a768464bdba: 0x018047bd 76543210flag=--------ntab=1nrow=1frre=-1fsbo=0x14fseo=0x40avsp=0xfd8tosp=0xfd80xe:pti[0] nrow=1 offs=00x12:pri[0] offs=0x40block_row_dump:tab 0, row 0, @0x40tl: 4012 fb: --H-F--- lb: 0x1 cc: 1nrid: 0x018047bc.0--链接的块的地址col 0: [4000] 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 ................................省略.....................................end_of_block_dump 转换nrid: select dbms_utility.DATA_BLOCK_ADDRESS_FILE(to_number('018047bc', 'xxxxxxxxxx')) file#, dbms_utility.DATA_BLOCK_ADDRESS_BLOCK(to_number('018047bc', 'xxxxxxxxxx')) block# from dual; alter system dump datafile 6 block 18364; System altered 链接块1data_block_dump,data header at 0xa76847c===============tsiz: 0x1f80hsiz: 0x14pbl: 0x0a76847cbdba: 0x018047bc 76543210flag=--------ntab=1nrow=1frre=-1fsbo=0x14fseo=0x2eavsp=0xfc0tosp=0xfc00xe:pti[0] nrow=1 offs=00x12:pri[0] offs=0x2eblock_row_dump:tab 0, row 0, @0x2etl: 4012 fb: -------- lb: 0x2 cc: 1nrid: 0x018047c0.0--链接的块的地址col 0: [4000] 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 ................................省略.....................................end_of_block_dump SQL>select dbms_utility.DATA_BLOCK_ADDRESS_FILE(to_number('018047c0', 'xxxxxxxxxx')) file#, dbms_utility.DATA_BLOCK_ADDRESS_BLOCK(to_number('018047c0', 'xxxxxxxxxx')) block# from dual;alter system dump datafile 6 block 18368; System altered 链接块2data_block_dump,data header at 0xa76847c===============tsiz: 0x1f80hsiz: 0x14pbl: 0x0a76847cbdba: 0x018047c0 76543210flag=--------ntab=1nrow=1frre=-1fsbo=0x14fseo=0xfdaavsp=0xfc6tosp=0xfc60xe:pti[0] nrow=1 offs=00x12:pri[0] offs=0xfdablock_row_dump:tab 0, row 0, @0xfdatl: 4006 fb: -----L-- lb: 0x3 cc: 1col 0: [4000] 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33................................省略.....................................end_of_block_dump
行迁移和行迁移的区别、危害
区别:可以看到行链接发生在update或insert,有一部分数据放在当前块,有一部分数据放在链接的块中。行迁移在当前块只放一个地址,内容全部在链接的块中,且可能有多个链接块。
危害:会引起额外的I/O操作。
如何检测出行迁移?
@?\RDBMS\ADMIN\utlchain.sql
analyze table 【table_name】 list chained rows into chained_rows;
select owner_name,table_name,head_rowid from chained_rows;
注意:如果要在正式环境上执行,不能在上班时间执行
如何避免和消除行迁移和行链接
Oracle® Database Performance Tuning Guide >> 10 Instance Tuning Using Performance Views
>>10.2.4.3 Table Fetch by Continued Row
行链接和行迁移检测和消除方法 :http://blog.csdn.net/guogang83/article/details/8671425
高水位线含义及问题
drop table test1 purge; create table test1 as select * from dba_objects; begin for i in 1 .. 100 loop execute immediate 'insert into test1 select * from dba_objects'; end loop; end; exec dbms_stats.gather_table_stats(user,'TEST1'); select count(*) from test1; delete from test1; select count(*) from test1;如何修正ORACLE表的高水位线
1.执行表重建指令 alter table table_name move; 2.执行alter table table_name shrink space; 注意,此命令为Oracle 10g新增功能,再执行该指令之前必须允许行移动alter table table_name enable row movement; 3.复制要保留的数据到临时表t,drop原表,然后rename临时表t为原表; 4.emp/imp; 5.alter table table_name deallocate unused ; 6.尽量truncate 。
Drop、Truncate、Delete的区别
语句类型上来区分
DDL和DML区别:Metadata(元数据:数据仓库中非常重要的概念,管理数据的数据,oracle中的数据字典据都可以理解成元数据)。DDL就是操作元数据的操作,自动提交。
安全性考虑
select * from recyclebin;