block和行迁移和行链接、高水位线



 

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;

注意:如果要在正式环境上执行,不能在上班时间执行

 

如何避免和消除行迁移和行链接

•不要插入一行数据,而一行带有大量NULL的列,更合适的是,从一开始插入数据就要填满行。
•使用增大block size的表空间。
•增大pctfree。

 

•重建表或索引。

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

 

高水位线含义及问题

 

•ORACLE用HWM来界定一个段中使用的块和未使用的块。 HWM在插入数据时,当现有空间不足而进行空间的扩展时会向上移,但删除数据时不会往下移。这就好比是水库的水位,当涨水时,水位往上移,当水退出后,最高水位的痕迹还是清淅可见。ORACLE的全表扫描是读取高水位标记(HWM)以下的所有块。
•高水位线带来的问题:如果在执行删除操作后不降低高水位线标记,则将导致查询语句的性能低下。
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的区别

语句类型上来区分

•delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,执行的时候将被触发。
•truncate是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger。
•Drop是ddl。

DDLDML区别:Metadata(元数据:数据仓库中非常重要的概念,管理数据的数据,oracle中的数据字典据都可以理解成元数据)DDL就是操作元数据的操作,自动提交。

安全性考虑

•如果没有备份,尽量不要用truncate。
•想保留表而将所有数据删除。如果和事务无关,用truncate即可。如果和事务有关,或者想触发trigger,还是用delete。
•想删除部分数据行用delete,注意带上where子句,回滚段要足够大。用delete误删数据后如何恢复。

 

•SELECT count(*) from pub_department AS OF TIMESTAMP TO_TIMESTAMP('2012-08-26 15:29:00', 'YYYY-MM-DD HH24:MI:SS');

select * from recyclebin;

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值