在线重定义功能

文章来自:

http://www.lunar2013.com/2014/07/%E6%B5%8B%E8%AF%95%E5%9C%A8%E7%BA%BF%E9%87%8D%E5%AE%9A%E4%B9%89%E5%8A%9F%E8%83%BD.html


9i开始,Oracle引入了在线重定义功能,但是bug比较多,10g时,如果数据量比较大,有些特殊场景,也有bug。
因此,前几天有同事需要测试在线重定义的功能,我查了下MOS,做个demo,做一个功能测试,如果生产上在低版本数据库执行在线重定义功能时,请仔细查看MOS上相关的常见问题。

22:28:49 SQL> select * from v $version;
 
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
PL /SQL Release 10.2.0.4.0 - Production
CORE    10.2.0.4.0      Production
TNS for Linux: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production
 
已用时间:  00: 00: 00.01
22:30:24 SQL> select 'www.lunar2013.com' lunar,sysdate from dual;
 
LUNAR                            SYSDATE
-------------------------------- --------------
www.lunar2013.com                05-7月 -14
 
已用时间:  00: 00: 00.00
22:31:11 SQL>

–创建测试表

CREATE TABLE unpar_table (
a NUMBER, y number,
name VARCHAR2(100), date_used date );
 
alter table unpar_table ADD (CONSTRAINT unpar_table_pk PRIMARY KEY (a,y));
 
-- load table with 1,000,000 rows
begin
     for i in 1 .. 1000
     loop
         for j in 1 .. 1000
         loop
         insert into unpar_table values ( i, j, dbms_random.random, sysdate-j );
         end loop;
     end loop;
end;
/
commit;

–收集统计信息

EXEC DBMS_STATS.gather_table_stats(user, 'unpar_table' , cascade => TRUE);
SELECT num_rows FROM user_tables WHERE table_name = 'UNPAR_TABLE' ;

–创建空的分区表

CREATE TABLE par_table (
a NUMBER, y number,
name VARCHAR2(100),date_used DATE)
PARTITION BY RANGE (date_used)
(PARTITION unpar_table_12 VALUES LESS THAN (TO_DATE( '10/07/2012' , 'DD/MM/YYYY' )),
PARTITION unpar_table_15 VALUES LESS THAN (TO_DATE( '15/07/2012' , 'DD/MM/YYYY' )),
PARTITION unpar_table_MX VALUES LESS THAN (MAXVALUE));

–执行Redefinition.can_redef_table,验证unpar_table表是否可以在线重定义,如果不可以会给出建议:
EXEC Dbms_Redefinition.can_redef_table(USER, ‘unpar_table’);
执行这一步的时候,如果缺少如下权限,那么会报如下错误:
第 1 行出现错误:
ORA-06550: 第 1 行, 第 7 列:
PLS-00201: 必须声明标识符 ‘DBMS_REDEFINITION’
ORA-06550: 第 1 行, 第 7 列:
解决方法:
grant execute on dbms_redefinition to lunar;

-- This procedure (DBMS_REDEFINITION.start_redef_table) creates a materialized view based on a CTAS, as we can see below with
-- the PREBUILT container table.
BEGIN
DBMS_REDEFINITION.start_redef_table(
uname => USER,
orig_table => 'unpar_table' ,
int_table => 'par_table' );
END;
/

执行这一步的时候,如果缺少如下权限,那么会报如下错误:
第 1 行出现错误:
ORA-01031: 权限不足
ORA-06512: 在 “SYS.DBMS_REDEFINITION”, line 50
ORA-06512: 在 “SYS.DBMS_REDEFINITION”, line 1343
ORA-06512: 在 line 2
解决方法:
grant create any table to lunar;
grant alter any table to lunar;
grant drop any table to lunar;
grant lock any table to lunar;
grant select any table to lunar;

22:16:46 SQL> select mview_name,container_name, build_mode from user_mviews;
 
MVIEW_NAME                     CONTAINER_NAME                 BUILD_MOD
------------------------------ ------------------------------ ---------
PAR_TABLE                      PAR_TABLE                      PREBUILT

–开启DBMS_REDEFINITION.start_redef_table后,向unpar_table表中插入1000行数据
此时,系统会使用mview log来记录该表的变化,可以查询MLOG$_UNPAR_TABLE来确认这一点:

begin
     for i in 1001 .. 1010
     loop
         for j in 1001 .. 1100
         loop
         insert into unpar_table values ( i, j, dbms_random.random, sysdate-j );
         end loop;
     end loop;
end;
/
commit;
 
22:17:07 SQL> select count(*) from MLOG$_UNPAR_TABLE;
 
   COUNT(*)
----------
       1000
 
已用时间:  00: 00: 00.01
22:17:12 SQL> select count(*) from unpar_table;
 
   COUNT(*)
----------
    1001000
 
已用时间:  00: 00: 00.07
22:17:27 SQL> select count(*) from par_table;
 
   COUNT(*)
----------
    1000000
 
已用时间:  00: 00: 00.20
22:17:48 SQL>

–执行dbms_redefinition.sync_interim_table,类似MVIEW FAST REFRESH
–该操作将MLOG$_UNPAR_TABLE的内容同步到par_table,并在同步后purge自己
–在执行dbms_redefinition.finish_redef_table之前,可以执行多次

BEGIN
dbms_redefinition.sync_interim_table(
uname => USER,
orig_table => 'unpar_table' ,
int_table => 'par_table' );
END;
 
22:18:35 SQL> select count(*) from MLOG$_UNPAR_TABLE;
 
   COUNT(*)
----------
          0
 
已用时间:  00: 00: 00.00
22:22:52 SQL> select count(*) from unpar_table;
 
   COUNT(*)
----------
    1001000
 
已用时间:  00: 00: 00.06
22:22:58 SQL> select count(*) from par_table;
 
   COUNT(*)
----------
    1001000
 
已用时间:  00: 00: 00.06
22:23:03 SQL>
 
ALTER TABLE par_table ADD (CONSTRAINT par_table_pk2 PRIMARY KEY (a,y));
EXEC DBMS_STATS.gather_table_stats(USER, 'par_table' , cascade => TRUE);

–完成在线重定义的操作,切换两个表:

BEGIN
dbms_redefinition.finish_redef_table(
uname => USER,
orig_table => 'unpar_table' ,
int_table => 'par_table' );
END;
/
 
22:27:49 SQL> select count(*) from MLOG$_UNPAR_TABLE;
select count(*) from MLOG$_UNPAR_TABLE
                      *
第 1 行出现错误:
ORA-00942: 表或视图不存在
 
 
已用时间:  00: 00: 00.00
22:28:02 SQL> select count(*) from unpar_table;
 
   COUNT(*)
----------
    1001000
 
已用时间:  00: 00: 00.06
22:28:10 SQL> select count(*) from par_table;
 
   COUNT(*)
----------
    1001000
 
已用时间:  00: 00: 00.06
22:28:15 SQL>
 
22:28:32 SQL> SELECT partitioned FROM user_tables WHERE table_name = 'UNPAR_TABLE' ;
 
PAR
---
YES
 
已用时间:  00: 00: 00.02
22:28:34 SQL> SELECT partition_name, num_rows FROM user_tab_partitions WHERE table_name = 'UNPAR_TABLE' ;
 
PARTITION_NAME                   NUM_ROWS
------------------------------ ----------
UNPAR_TABLE_12                     274384
UNPAR_TABLE_15                       5000
UNPAR_TABLE_MX                     721140
 
已用时间:  00: 00: 00.13
22:28:38 SQL>
 
22:28:38 SQL> drop TABLE par_table cascade constraints;
 
表已删除。
 
已用时间:  00: 00: 00.06
22:28:49 SQL>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值