11G的online redefinition有了不少功能增强,相信大家都在其他地方早已经看到这些概念,于是不再废话,直接来看一下我们可能常常需要问到的几种实际例子。
1.Add column
11G的alter table add column操作已经有了不小改进,尤其是对add column with default value采用ecol$表存储default value从而避免了对整表的update操作,但也因此引入了不断对ecol$表的查询的overhead。于是,此时我们想到了online redefinition。
--建测试表的SQL(分别建立各种相关的object用来测试):
--按照官方文档,trigger是不会自动recompile的,其他一般在online redefinition之后都为valid的状态,省去了DBA的麻烦。
create table hao(object_id,object_name,status) tablespace test_assm
as select object_id,object_name,status from dba_objects;
alter table hao add constraint haopk primary key (object_id);
create public synonym synhao for hao;
create view viewhao as select * from hao;
create or replace trigger thao before insert on hao for each row
declare
v_d hao%rowtype;
begin
select * into v_d from hao where rownum=1;
end;
/
--建立TMPHAO作为中间表,并且add new column
SQL> create table tmphao as select * from hao where 1=2;
Table created.
SQL> alter table tmphao add object_id2 number;
Table altered.
SQL> select object_name,object_type,status from user_objects;
OBJECT_NAM OBJECT_TYPE STATUS
---------- ------------------- -------
HAO TABLE VALID
HAOPK INDEX VALID
THAO TRIGGER VALID
TMPHAO TABLE VALID
VIEWHAO VIEW VALID
SQL> BEGIN
2 DBMS_REDEFINITION.CAN_REDEF_TABLE(UNAME=>'HAO',TNAME=>'HAO',OPTIONS_FLAG=>DBMS_REDEFINITION.CONS_USE_PK);
3 END;
4 /
PL/SQL procedure successfully completed.
--这里我设定新加的column的default value为0
SQL> BEGIN
2 DBMS_REDEFINITION.START_REDEF_TABLE('HAO', 'HAO','TMPHAO',
3 'object_id object_id,object_name object_name,status status,0 object_id2',dbms_redefinition.cons_use_pk);
4 END;
5 /
PL/SQL procedure successfully completed.
--我们看到开始重定义时,为了保证在该表的并发dml操作,其实是通过建立MV log来保证的。
SQL> select table_name from user_tables;
TABLE_NAME
------------------------------
HAO
MLOG$_HAO
RUPD$_HAO
TMPHAO
SQL> insert into hao values(1986000,'1986','1');
1 row created.
SQL> commit;
Commit complete.
SQL> select DMLTYPE$$,OLD_NEW$$ from MLOG$_HAO;
D O
- -
I N
SQL> DECLARE
2 num_errors PLS_INTEGER;
3 BEGIN
4 DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('HAO', 'HAO','TMPHAO',
5 DBMS_REDEFINITION.CONS_ORIG_PARAMS, TRUE, TRUE, TRUE, TRUE, num_errors);
6 END;
7 /
PL/SQL procedure successfully completed.
SQL> select object_name, base_table_name, ddl_txt from
2 DBA_REDEFINITION_ERRORS;
no rows selected
--而DBMS_REDEFINITION.SYNC_INTERIM_TABLE的作用有点像对MV的一次fast refresh,以减少finish online redefinition的lock时间。
SQL> BEGIN
2 DBMS_REDEFINITION.SYNC_INTERIM_TABLE('HAO', 'HAO', 'TMPHAO');
3 END;
4 /
PL/SQL procedure successfully completed.
SQL> select DMLTYPE$$,OLD_NEW$$ from MLOG$_HAO;
no rows selected
SQL> BEGIN
2 DBMS_REDEFINITION.FINISH_REDEF_TABLE('HAO', 'HAO', 'TMPHAO');
3 END;
4 /
PL/SQL procedure successfully completed.
SQL> select table_name from user_tables;
TABLE_NAME
------------------------------
HAO
TMPHAO
--这里我们看到view和trigger为INVALID,trigger可以理解,但view为什么呢?
--原来是因为view里有select *的字样,oracle自动转换为当时的具体字段,所以这点要注意。
--而trigger里也有select *,但是并没有转换为当时的具体字段。
SQL> select object_name,object_type,status from user_objects;
OBJECT_NAME OBJECT_TYPE STATUS
-------------------- ------------------- -------
HAO TABLE VALID
HAOPK INDEX VALID
THAO TRIGGER INVALID
TMP$$_HAOPK0 INDEX VALID
TMP$$_THAO0 TRIGGER INVALID
TMPHAO TABLE VALID
VIEWHAO VIEW INVALID
SQL> select text from user_views;
TEXT
--------------------------------------------------------------------------------
select "OBJECT_ID","OBJECT_NAME","STATUS" from hao
SQL> select trigger_body from user_triggers where trigger_name='THAO';
TRIGGER_BODY
--------------------------------------------------------------------------------
declare
v_d hao%rowtype;
begin
select * into v_d from hao where rownum=1;
end;
--我们可以通过触发view和trigger一次,就可以让其自动recompile为VALID状态。
SQL> select * from VIEWHAO where rownum=1;
OBJECT_ID OBJECT_NAME STATUS
---------- -------------------- -------
105 ACCESS$ VALID
SQL> insert into hao values(999999,'999999','9','0');
1 row created.
SQL> insert into tmphao values(999999,'999999','9');
1 row created.
SQL> select object_name,object_type,status from user_objects;
OBJECT_NAME OBJECT_TYPE STATUS
-------------------- ------------------- -------
HAO TABLE VALID
HAOPK INDEX VALID
THAO TRIGGER VALID
TMP$$_HAOPK0 INDEX VALID
TMP$$_THAO0 TRIGGER VALID
TMPHAO TABLE VALID
VIEWHAO VIEW VALID
--synonym也为INVALID状态,只需引用一次即可。
SQL> select OBJECT_NAME,OBJECT_TYPE,STATUS from dba_objects where OBJECT_NAME='SYNHAO';
OBJECT_NAME OBJECT_TYPE STATUS
-------------------- ------------------- -------
SYNHAO SYNONYM INVALID
SQL> show parameter compatible
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
compatible string 11.2.0.1
SQL> select * from SYNHAO where rownum=1;
OBJECT_ID OBJECT_NAME STATUS OBJECT_ID2
---------- -------------------- ------- ----------
105 ACCESS$ VALID 0
SQL> select OBJECT_NAME,OBJECT_TYPE,STATUS from dba_objects where OBJECT_NAME='SYNHAO';
OBJECT_NAME OBJECT_TYPE STATUS
-------------------- ------------------- -------
SYNHAO SYNONYM VALID
--除此之外,我在《在线重定义表导致constraint变成novalidate》里专门提到过这种情况:
SQL> l
1 select CONSTRAINT_NAME,TABLE_NAME,STATUS,VALIDATED from user_constraints
2* where CONSTRAINT_NAME='HAOPK'
SQL> /
CONSTRAINT_NAME TABLE_NAME STATUS VALIDATED
------------------------------ ------------------------------ -------- -------------
HAOPK HAO ENABLED NOT VALIDATED
SQL> alter table hao enable validate primary key;
Table altered.
SQL> select CONSTRAINT_NAME,TABLE_NAME,STATUS,VALIDATED from user_constraints
2 where CONSTRAINT_NAME='HAOPK'
3 ;
CONSTRAINT_NAME TABLE_NAME STATUS VALIDATED
------------------------------ ------------------------------ -------- -------------
HAOPK HAO ENABLED VALIDATED
--如果我们在online redefinition过程中遇到任何Error,都可以立即终止:
BEGIN
DBMS_REDEFINITION.ABORT_REDEF_TABLE('HAO', 'HAO','TMPHAO');
END;
/
2.普通表转为partition table
--建立TMPHAO2为一个range partition table作为中间表
create table tmphao2
(OBJECT_ID NUMBER,
OBJECT_NAME VARCHAR2(128),
STATUS VARCHAR2(7),
OBJECT_ID2 NUMBER)
partition by range(OBJECT_ID)
(partition p1 values less than(10),
partition p2 values less than(20),
partition p3 values less than(maxvalue)
);
--同样的命令,只是记得查看所有invalid的objects。
SQL> BEGIN
2 DBMS_REDEFINITION.CAN_REDEF_TABLE(UNAME=>'HAO',TNAME=>'HAO',OPTIONS_FLAG=>DBMS_REDEFINITION.CONS_USE_PK);
3 END;
4 /
PL/SQL procedure successfully completed.
SQL> BEGIN
2 DBMS_REDEFINITION.START_REDEF_TABLE('HAO', 'HAO','TMPHAO2',
3 '*',dbms_redefinition.cons_use_pk);
4 END;
5 /
SQL> DECLARE
2 num_errors PLS_INTEGER;
3 BEGIN
4 DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('HAO', 'HAO','TMPHAO2',
5 DBMS_REDEFINITION.CONS_ORIG_PARAMS, TRUE, TRUE, TRUE, TRUE, num_errors);
6 END;
7 /
PL/SQL procedure successfully completed.
SQL> select object_name, base_table_name, ddl_txt from
2 DBA_REDEFINITION_ERRORS;
no rows selected
SQL> BEGIN
2 DBMS_REDEFINITION.FINISH_REDEF_TABLE('HAO', 'HAO', 'TMPHAO2');
3 END;
4 /
PL/SQL procedure successfully completed.
SQL> select PARTITION_NAME from user_tab_partitions where TABLE_NAME='HAO';
PARTITION_NAME
------------------------------
P1
P2
P3
3.更改被index的column name。
--这时我在前面的HAO的object_id2上建立index。
SQL> create index haoidx2 on HAO(object_id2) local;
Index created.
--在TMPHAO3中将object_id2改为object_id3
--如果直接DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS,会报错说找不到object_id2这个column。
--所以需要我们手工register
create table tmphao3
(OBJECT_ID NUMBER,
OBJECT_NAME VARCHAR2(128),
STATUS VARCHAR2(7),
OBJECT_ID3 NUMBER)
partition by range(OBJECT_ID)
(partition p1 values less than(10),
partition p2 values less than(20),
partition p3 values less than(maxvalue)
);
SQL> create index haoidx3 on tmphao3(object_id3) local;
Index created.
exec DBMS_REDEFINITION.CAN_REDEF_TABLE(UNAME=>'HAO',TNAME=>'HAO',OPTIONS_FLAG=>DBMS_REDEFINITION.CONS_USE_PK);
BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE('HAO', 'HAO','TMPHAO3',
'OBJECT_ID OBJECT_ID,OBJECT_NAME OBJECT_NAME,STATUS STATUS,OBJECT_ID2 OBJECT_ID3',dbms_redefinition.cons_use_pk);
END;
/
BEGIN
DBMS_REDEFINITION.REGISTER_DEPENDENT_OBJECT(
uname => 'HAO',
orig_table => 'HAO',
int_table => 'TMPHAO3',
dep_type => DBMS_REDEFINITION.CONS_INDEX,
dep_owner => 'HAO',
dep_orig_name => 'HAOIDX2',
dep_int_name => 'HAOIDX3');
END;
/
DECLARE
num_errors PLS_INTEGER;
BEGIN
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('HAO', 'HAO','TMPHAO3',
DBMS_REDEFINITION.CONS_ORIG_PARAMS, TRUE, TRUE, TRUE, TRUE, num_errors);
END;
/
SQL> select object_name, base_table_name, ddl_txt from
2 DBA_REDEFINITION_ERRORS;
no rows selected
exec DBMS_REDEFINITION.FINISH_REDEF_TABLE('HAO', 'HAO', 'TMPHAO3');
SQL> l
1* select INDEX_NAME,COLUMN_NAME from user_ind_columns where TABLE_NAME='HAO'
SQL> /
INDEX_NAME COLUMN_NAM
------------------------------ ----------
HAOIDX2 OBJECT_ID3
HAOPK OBJECT_ID
4.更改表所在的tablespace
过程完全如前。只是中间表建立在所期望的tablespace上。
5.long转换为clob,long raw转换为blob
create table hao2 (id number primary key,name long);
insert into hao2 select object_id,'hao' from dba_objects;
create table tmp_hao2 (id number,name clob);
BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE('HAO', 'HAO2','TMP_HAO2',
'id id,to_lob(name) name',dbms_redefinition.cons_use_pk);
END;
/
DECLARE
num_errors PLS_INTEGER;
BEGIN
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('HAO', 'HAO2','TMP_HAO2',
DBMS_REDEFINITION.CONS_ORIG_PARAMS, TRUE, TRUE, TRUE, TRUE, num_errors);
END;
/
SQL> select object_name, base_table_name, ddl_txt from
2 DBA_REDEFINITION_ERRORS;
no rows selected
exec DBMS_REDEFINITION.FINISH_REDEF_TABLE('HAO', 'HAO2', 'TMP_HAO2');
SQL> desc hao2
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER
NAME CLOB
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15415488/viewspace-626671/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/15415488/viewspace-626671/