Oracle的在线重定义功能就是利用了物化视图的功能,通过物化视图日志的记录功能,来同步目标表和基表的数据。因此,在11g以前,建立了物化视图日志的表是无法进行在线重定义操作的:
SQL > CREATE TABLE T AS SELECT ROWNUM ID, A. * FROM DBA_OBJECTS A; 表已创建。 SQL > CREATE INDEX IND_T_NAME ON T ( OBJECT_NAME ); 索引已创建。 SQL > ALTER TABLE T ADD CONSTRAINTS PK_T PRIMARY KEY (ID); 表已更改。 SQL > BEGIN 2 DBMS_REDEFINITION.CAN_REDEF_TABLE( USER , ' T ' ); 3 END ; 4 / PL / SQL 过程已成功完成。 SQL > CREATE MATERIALIZED VIEW LOG ON T; 实体化视图日志已创建。 SQL > BEGIN 2 DBMS_REDEFINITION.CAN_REDEF_TABLE( USER , ' T ' ); 3 END ; 4 / BEGIN * 第 1 行出现错误: ORA - 12091 : 不能联机重新定义具有实体化视图的表 "YANGTK"."T" ORA - 06512 : 在 "SYS.DBMS_REDEFINITION", line 137 ORA - 06512 : 在 "SYS.DBMS_REDEFINITION", line 1478 ORA - 06512 : 在 line 2 SQL > SELECT * FROM V$VERSION; BANNER -- -------------------------------------------------------------- Oracle Database 10g Enterprise Edition Release 10.2 . 0.1 . 0 - Prod PL / SQL Release 10.2 . 0.1 . 0 - Production CORE 10.2 . 0.1 . 0 Production TNS for 32 - bit Windows: Version 10.2 . 0.1 . 0 - Production NLSRTL Version 10.2 . 0.1 . 0 - Production
在11g中,Oracle会利用现有的物化视图日志来完成在线重定义的功能。同时,物化视图日志也可以作为表的从属信息同步到目标上。不过在同步完成后,需要物化视图执行完全刷新。
SQL > CREATE TABLE T AS SELECT ROWNUM ID, A. * FROM USER_OBJECTS A; 表已创建。 SQL > CREATE INDEX IND_T_NAME ON T ( OBJECT_NAME ); 索引已创建。 SQL > ALTER TABLE T ADD CONSTRAINT PK_T PRIMARY KEY (ID); 表已更改。 SQL > CREATE MATERIALIZED VIEW LOG ON T; 实体化视图日志已创建。 SQL > BEGIN 2 DBMS_REDEFINITION.CAN_REDEF_TABLE( USER , ' T ' ); 3 END ; 4 / PL / SQL 过程已成功完成。 SQL > SELECT * FROM V$VERSION; BANNER -- ----------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.1 . 0.6 . 0 - Production PL / SQL Release 11.1 . 0.6 . 0 - Production CORE 11.1 . 0.6 . 0 Production TNS for Linux: Version 11.1 . 0.6 . 0 - Production NLSRTL Version 11.1 . 0.6 . 0 - Production
最后简单给出11g中包含物化视图日志的在线重定义操作步骤:
SQL > CREATE MATERIALIZED VIEW MV_T REFRESH FAST AS SELECT * FROM T; 实体化视图已创建。 SQL > DELETE T WHERE ID = 1 ; 已删除 1 行。 SQL > COMMIT ; 提交完成。 SQL > SELECT COUNT ( * ) FROM T; COUNT ( * ) -- -------- 23 SQL > SELECT COUNT ( * ) FROM MV_T; COUNT ( * ) -- -------- 24 SQL > CREATE TABLE T_INTER PARTITION BY HASH (ID) 2 PARTITIONS 4 3 AS SELECT ROWNUM ID, A. * FROM USER_OBJECTS A WHERE 1 = 2 ; 表已创建。 SQL > BEGIN 2 DBMS_REDEFINITION.START_REDEF_TABLE( USER , ' T ' , ' T_INTER ' ); 3 END ; 4 / PL / SQL 过程已成功完成。 SQL > VAR V_NUM NUMBER SQL > BEGIN 2 DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS( USER , ' T ' , ' T_INTER ' , COPY_MVLOG => TRUE, NUM_ERRORS = > :V_NUM); 3 END ; 4 / PL / SQL 过程已成功完成。 SQL > PRINT :V_NUM V_NUM -- -------- 0 SQL > SELECT COUNT ( * ) FROM T; COUNT ( * ) -- -------- 23 SQL > SELECT COUNT ( * ) FROM T_INTER; COUNT ( * ) -- -------- 23 SQL > DELETE T WHERE ID = 2 ; 已删除 1 行。 SQL > COMMIT ; 提交完成。 SQL > BEGIN 2 DBMS_REDEFINITION.SYNC_INTERIM_TABLE( USER , ' T ' , ' T_INTER ' ); 3 END ; 4 / PL / SQL 过程已成功完成。 SQL > SELECT COUNT ( * ) FROM T_INTER; COUNT ( * ) -- -------- 22 SQL > BEGIN 2 DBMS_REDEFINITION.FINISH_REDEF_TABLE( USER , ' T ' , ' T_INTER ' ); 3 END ; 4 / PL / SQL 过程已成功完成。 SQL > SELECT TABLE_NAME, PARTITION_NAME FROM USER_TAB_PARTITIONS WHERE TABLE_NAME = ' T ' ; TABLE_NAME PARTITION_NAME -- ---------------------------- ------------------------------ T SYS_P45 T SYS_P46 T SYS_P47 T SYS_P48 SQL > EXEC DBMS_MVIEW.REFRESH( ' MV_T ' ) BEGIN DBMS_MVIEW.REFRESH( ' MV_T ' ); END ; * 第 1 行出现错误: ORA - 12034 : "YANGTK"."T" 上的实体化视图日志比上次刷新后的内容新 ORA - 06512 : 在 "SYS.DBMS_SNAPSHOT", line 2537 ORA - 06512 : 在 "SYS.DBMS_SNAPSHOT", line 2743 ORA - 06512 : 在 "SYS.DBMS_SNAPSHOT", line 2712 ORA - 06512 : 在 line 1 SQL > EXEC DBMS_MVIEW.REFRESH( ' MV_T ' , ' C ' ) PL / SQL 过程已成功完成。 SQL > DELETE T WHERE ID = 3 ; 已删除 1 行。 SQL > COMMIT ; 提交完成。 SQL > EXEC DBMS_MVIEW.REFRESH( ' MV_T ' ) PL / SQL 过程已成功完成。 SQL > SELECT * FROM MV_T WHERE ID = 3 ; 未选定行
11g在线重定义对物化视图日志进行了支持,同时COPY_TABLE_DEPENDENTS过程也添加了对物化视图日志拷贝的功能。