测试在线重定义功能

联系:QQ(5163721)

标题:测试在线重定义功能

作者:Lunar©版权所有[文章允许转载,但必须以链接方式注明源地址,否则追究法律责任.]

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> 
此条目发表在 FAQ 分类目录,贴了 , 标签。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注