利用DBMS_REDEFINITION在线重定义表
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://asktom.oracle.com/pls/asktom/f?p=100:11:1619565279119772::::P11_QUESTION_ID:4636779130376
http://roujiaweize.spaces.live.com/blog/cns!9745F14B4AEB3B72!818.entry
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:Incessant 来源: Incessant
- 标签: DBMS_REDEFINITIO
- 发布时间:2009-10-11 22:21:46
- [67] Go Reflect 性能
- [66] Oracle MTS模式下 进程地址与会话信
- [63] 如何拿下简短的域名
- [61] android 开发入门
- [60] 【社会化设计】自我(self)部分――欢迎区
- [59] IOS安全–浅谈关于IOS加固的几种方法
- [59] 图书馆的世界纪录
- [54] 视觉调整-设计师 vs. 逻辑
- [49] 读书笔记-壹百度:百度十年千倍的29条法则
- [48] 界面设计速成