技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> Oracle --> 利用DBMS_REDEFINITION在线重定义表

利用DBMS_REDEFINITION在线重定义表

浏览:1603次  出处信息

    7*24的业务运营系统中,对一个表进行在线重定义将是很棘手的事,因为业务实时的在对这个表进行进行插入,删除修改等操作,那么是否可以在线重定义表呢,Oracle9i提供了在线重定义表包(DBMS_REDEFINITION),在修改表结构的同时可以进行DML操作。

    1.构造原始数据表

    SQL> create table red_test --原始表,需要对这个表进行在线重定义

     2 as

     3 select te_seq.nextval as id ,t.owner,t.object_name,10 as tvalue from dba_objects t ;

    Table created

    SQL> alter table RED_TEST --增加主键

     2 add constraint pri_redtest primary key (id);

    Table altered

    SQL> create index idc_retest_owner on red_test(owner) ;

    Index created

    需求:把red_test进行在线重定义,把tvuale字段更改为sal字段,并且sal=tvalue*10

    2.验证是否可以在线重定义

    SQL> EXEC Dbms_Redefinition.Can_Redef_Table(\'etl\', \'red_test\',DBMS_REDEFINITION.CONS_USE_PK);

    PL/SQL procedure successfully completed

    3.建立中间表

    SQL> CREATE TABLE RED_TEST_MIDDLE AS

     2 SELECT id,owner,object_name,tvalue as sal FROM red_test WHERE 1=2;

    Table created

    SQL> alter table RED_TEST_MIDDLE

     2 add constraint pri_redtest123 primary key (id);

    Table altered

    4.进行在线重定义

    SQL> EXEC Dbms_Redefinition.Start_Redef_Table( \'ETL\',\'RED_TEST\',\'RED_TEST_MIDDLE\',\'ID

     ID, OWNER OWNER, OBJECT_NAME OBJECT_NAME,TVALUE*10 SAL\');

    PL/SQL procedure successfully completed

    6.同步中间表,主要是同步重定义过程中变化的数据

    SQL> EXEC dbms_redefinition.sync_interim_table(\'ETL\', \'RED_TEST\', \'RED_TEST_MIDDLE\');

    PL/SQL procedure successfully completed

    7.测试在原始表继续插入是否还会同步

    SQL> insert into RED_TEST select te_seq.nextval as id ,t.owner,t.object_name,999 from dba_objects t ;

    34193 rows inserted

    SQL> commit;

    Commit complete

    --重定义过程原始表发生dml的数据会保留MV log,这就是为什么原始表要有主键的原因,当然也可以利用rowid

    SQL> select count(*) from Mlog$_red_test;--原始产生的dml操作会记录在mv log

     COUNT(*)

    ----------

     34193

    8.完成重定义

    SQL> EXEC Dbms_Redefinition.Finish_Redef_Table( \'ETL\', \'RED_TEST\', \'RED_TEST_MIDDLE\');

    PL/SQL procedure successfully completed

    9.检查是否完成了重定义

    SQL> select ix.table_name,ix.index_name from user_indexes ix where ix.table_name=\'RED_TEST\';

    TABLE_NAME INDEX_NAME

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

    RED_TEST PRI_REDTEST123

    SQL> select ix.table_name,ix.index_name from user_indexes ix where ix.table_name=\'RED_TEST_MIDDLE\' ;

    TABLE_NAME INDEX_NAME

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

    RED_TEST_MIDDLE IDC_RETEST_OWNER

    RED_TEST_MIDDLE PRI_REDTEST

    --比较一下中间表和原始表的索引,发觉仅仅是同步了数据,索引并不能同步过去,所以在正式环境中,应该先建立索引在完成重定义,建立索引可以放在第5步来做

    10.删除中间表

    SQL> drop table RED_TEST_MIDDLE ;

    Table dropped

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

    一般会有这个需求,需要将在线大表(5G以上)更改为分区表,Dbms_Redefinition在线重定义非常慢,可能需要好几个小时,大表又是实时的业务操作,这就存在很大的失败风险。有朋友曾经在线重定义过程中失败导致业务瘫痪,建议还是少用,或是不用,知道有这么回事就可以了。

    个人觉得如下步骤比较保险,但是需要停机

    a) export the table

    b) create a new empty table that has the partition definition on it

    c) import the table with IGNORE=Y

    参考:

    http://orafaq.com/node/4

    http://asktom.oracle.com/pls/asktom/f?p=100:11:1619565279119772::::P11_QUESTION_ID:4636779130376

    http://roujiaweize.spaces.live.com/blog/cns!9745F14B4AEB3B72!818.entry

QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1