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