ITPub博客

首页 > Linux操作系统 > Linux操作系统 > Rollback和Segment Allocation

Rollback和Segment Allocation

原创 Linux操作系统 作者:realkid4 时间:2013-10-31 22:25:19 0 删除 编辑

 

在笔者刚开始写Blog的时候,花了很多精力在HWM高水位线上,也写了几篇浅显的文章。前几天又有一个朋友遇到了类似的问题,突然想到几个相关问题。实验之后,略有收获,仅供分享。

 

1、环境介绍

 

笔者选择Oracle 11gR2进行试验,实验数据表T

 

 

SQL> select * from v$version;

 

BANNER

--------------------------------------------------------------------------------

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

PL/SQL Release 11.2.0.1.0 - Production

CORE        11.2.0.1.0         Production

 

TNS for Linux: Version 11.2.0.1.0 - Production

NLSRTL Version 11.2.0.1.0 - Production

 

 

数据表T为一个空表。

 

 

SQL> create table t as select * from dba_objects where 1=0;

Table created

 

 

 

2rollback操作

 

第一个思考的问题是,当我们插入一批数据,在没有commit的时候,对应的数据其实是已经写入到内存块的,起码是有对应的redo log信息。那么内存中写入的数据也需要对应分配数据块存储空间。也就是,这个过程中是有分配allocate动作的。

 

如果我们rollback数据,插入的数据被取消,插入数据不会显示出来。但是对应的空间是不是回收呢?Oracle的世界中,没有公开的代码,只有通过各种实验来验证。

 

初始数据段segment空间0.06M,进行一次插入动作。

 

 

SQL> select bytes/1024/1024 from dba_segments where wner='SYS' and segment_name='T';

 

BYTES/1024/1024

---------------

         0.0625

 

SQL> insert into t select * from dba_objects;

72757 rows inserted

 

SQL> select bytes/1024/1024 from dba_segments where wner='SYS' and segment_name='T';

 

BYTES/1024/1024

---------------

              9

 

 

插入动作,没有提交commit时候,我们看到段结构已经发生变化,膨胀到了9M。之后,我们rollback

 

 

SQL> rollback;

Rollback complete

 

SQL> select bytes/1024/1024 from dba_segments where wner='SYS' and segment_name='T';

 

BYTES/1024/1024

---------------

              9

 

 

Rollback之后,数据量比定位0,但是由此分配的空间不会回收。Oracle中,逻辑存储空间分配一直是有“覆水难收”的。对于堆表而言,插入数据如果在HWM之上,即使将来删除了数据,空闲空间也是不会回收的。上面实验证明了,即使数据没有真实被持久化commit,空间也是被分配,水位线同样上升。

 

3rollback与持续insert

 

一般insert操作对堆表而言,首先在HWM之下找空闲空间,如果找到就保存其中。如果HWM下面没有空闲空间,就会向上推动HWM,推动空间分配。只有加入append hint,不会在HWM下面找空闲,而直接向上推动HWM

 

上面的实验,告诉我们即使数据rollback了,也会有新空间分配,HWM向上推动。那么,如果我们持续的进行insert append操作,每次insert之后都会rollback,会不会出现单向数据表体积增大的情况呢?

 

 

SQL> truncate table t;

Table truncated

 

SQL>  insert /*+append */ into t select * from dba_objects where rownum<20000;

 

19999 rows inserted

 

SQL> select bytes/1024/1024 from dba_segments where wner='SYS' and segment_name='T';

 

BYTES/1024/1024

---------------

              3

 

SQL> rollback;

Rollback complete

 

SQL>  insert /*+append */ into t select * from dba_objects;

 

72757 rows inserted

 

SQL> select bytes/1024/1024 from dba_segments where wner='SYS' and segment_name='T';

 

BYTES/1024/1024

---------------

              9

 

SQL> rollback;

Rollback complete

 

 

从上面的情况看,当我们一次推动HWM上升,但是被rollback注意,第一次插入的数据只有20000条,大约3M空间。第二次插入的时候,我们使用append,应该在3M的基础上增加9M,总数为12M

 

但是实际情况只是补全了缺乏的6M,总数为9M

 

这个现象说明对于insert推动HWM上升之后,如果rollback了。空间虽然算已经分配的,但是第二次在使用的时候不会轻易的进行append推动HWM上升。

 

4commitappend

 

那么,如何实现这样持续的HWM推动呢?问题关键在于commit动作。每次进行append操作之后,如果不是进行rollback而是commit,哪怕事后删除,下次的append同样会推动HWM

 

 

SQL> truncate table t;

Table truncated

 

SQL> declare

  2    i number;

  3  begin

  4    for i in 1..10 loop

  5        insert /*+append*/ into t

  6            select * from dba_objects;

  7        commit;

  8 

  9        delete t;

 10        commit;

 11    end loop;

 12  end;

 13  /

 

PL/SQL procedure successfully completed

 

 

上面持续进行了10次动作,查看segment结构。

 

 

SQL> select bytes/1024/1024 from dba_segments where wner='SYS' and segment_name='T';

 

BYTES/1024/1024

---------------

             88

 

 

此时一行数据也不存在。

 

 

SQL> select count(*) from t;

 

  COUNT(*)

----------

         0

 

 

5、结论

 

几个简单的实验,其实里面有不少的启示。我们在设计应用系统的时候,数据库不恰当的使用经常引起HWM异常故障。

 

那么,HWM究竟应该是如何状态呢?笔者认为,如果设计合理,任何系统中任何数据表的数据都是维持一个相对稳定的数据量,也就是稳定的HWM位置。很多时候,如使用SQL Loader或者批量加载中间表,会引起HWM的位置剧烈变化。HWM剧烈变化的下一步往往也就是系统性能问题的开始。

 

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

请登录后发表评论 登录
全部评论
求道~

注册时间:2010-11-30

  • 博文量
    545
  • 访问量
    7629734