之前的两篇博文中,列举了两个单表在线重定义的过程:
Online Redefinition在线重定义(一):http://blog.itpub.net/31015730/viewspace-2144544/
Online Redefinition在线重定义(二)--单表复杂案例 : http://blog.itpub.net/31015730/viewspace-2144603/
但是在生产环境下,很多表之间都是有关联关系,本篇我们就来看一下如何对多个关联表进行在线重定义重定义,将普通表改造成分区表
需求:将外键关联的两张表进行在线重定义,改造成分区表
--首先创建两张实验数据表t_wjq2_master和t_wjq2_slave。
SEIANG@seiang11g>create table t_wjq2_master as select owner,table_name,tablespace_name,status from dba_tables where 1=2;
Table created.
--在表t_wjq2_master的owner和table_name列上创建主键约束
SEIANG@seiang11g>alter table t_wjq2_master add constraint pk_t_wjq2_master primary key(owner,table_name);
Table altered.
SEIANG@seiang11g>create table t_wjq2_slave as select owner,table_name,column_name from dba_tab_columns where 1=2;
Table created.
--在表t_wjq2_slave的owner、table_name和column_name列上创建主键约束
SEIANG@seiang11g>alter table t_wjq2_slave add constraint pk_t_wjq2_slave primary key(owner,table_name,column_name);
Table altered.
--分别在表t_wjq2_master和t_wjq2_slave中插入数据
SEIANG@seiang11g>insert into t_wjq2_master select owner,table_name,tablespace_name,status from dba_tables;
2881 rows created.
SEIANG@seiang11g>
SEIANG@seiang11g>insert into t_wjq2_slave select owner,table_name,column_name from dba_tab_columns where (owner,table_name) in (select owner,table_name from dba_tables);
31434 rows created.
--在t_wjq2_slave上创建外键约束,参考t_wjq2_master表,是的这两张表主子表关系
SEIANG@seiang11g>alter table t_wjq2_slave add constraint fk_t_wjq2_slave foreign key(owner,table_name) references t_wjq2_master(owner,table_name);
Table altered.
--查看表上的约束
SEIANG@seiang11g>select owner,constraint_name,constraint_type,table_name from user_constraints;
OWNER CONSTRAINT_NAME C TABLE_NAME
-------------------- ------------------------------ - ------------------------------
SEIANG FK_T_WJQ2_SLAVE R T_WJQ2_SLAVE
SEIANG PK_T_WJQ2_SLAVE P T_WJQ2_SLAVE
SEIANG PK_T_WJQ2_MASTER P T_WJQ2_MASTER
SEIANG SYS_C0011655 C T_WJQ2_MASTER
SEIANG SYS_C0011656 C T_WJQ2_MASTER
SEIANG SYS_C0011658 C T_WJQ2_SLAVE
SEIANG SYS_C0011659 C T_WJQ2_SLAVE
SEIANG SYS_C0011660 C T_WJQ2_SLAVE
--创建中间表,主要目标是将数据表按照owner进行分区,转化为分区表
SEIANG@seiang11g>create table t_wjq2_master_interim(
2 OWNER VARCHAR2(30),
3 TABLE_NAME VARCHAR2(30),
4 TABLESPACE_NAME VARCHAR2(30),
5 STATUS VARCHAR2(8)
6 )
7 partition by list(owner)
8 (
9 partition p1 values ('SYS'),
10 partition p2 values (default)
11 );
Table created.
Elapsed: 00:00:00.02
SEIANG@seiang11g>create table t_wjq2_slave_interim(
2 owner varchar2(30),
3 table_name varchar2(30),
4 column_name varchar2(30)
5 )
6 partition by list(owner)
7 (
8 partition p1 values ('SYS'),
9 partition p2 values (default)
10 );
Table created.
Elapsed: 00:00:00.02
--判断两张表t_wjq2_master和t_wjq2_slave是否可以进行在线重定义
SEIANG@seiang11g>exec dbms_redefinition.can_redef_table('SEIANG','T_WJQ2_MASTER',options_flag => dbms_redefinition.cons_use_pk);
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.03
SEIANG@seiang11g>exec dbms_redefinition.can_redef_table('SEIANG','T_WJQ2_SLAVE',options_flag => dbms_redefinition.cons_use_pk);
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.01
注:如果从安全和顺序关系看,应该是先子表后主表似乎好一点
--开始在线重定义,首先对t_wjq2_master表进行重定义
SEIANG@seiang11g>exec dbms_redefinition.start_redef_table('SEIANG','T_WJQ2_MASTER','T_WJQ2_MASTER_INTERIM',col_mapping => 'owner owner, table_name table_name, tablespace_name tablespace_name, status status',options_flag => dbms_redefinition.cons_use_pk);
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.98
--验证数据是否已经刷过去了
SEIANG@seiang11g>select count(*) from t_wjq2_master;
COUNT(*)
----------
2881
Elapsed: 00:00:00.00
SEIANG@seiang11g>
SEIANG@seiang11g>select count(*) from t_wjq2_master_interim;
COUNT(*)
----------
2881
Elapsed: 00:00:00.01
--执行表同步
注:这一步不是必须的,但是对于比较大的表,中间运行增量同步有助于减少切换时间
SEIANG@seiang11g> exec dbms_redefinition.sync_interim_table('SEIANG','T_WJQ2_MASTER','T_WJQ2_MASTER_INTERIM');
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.04
SEIANG@seiang11g>declare
2 error_count number:=0;
3 begin
4 dbms_redefinition.copy_table_dependents(
5 uname => 'SEIANG',orig_table => 'T_WJQ2_MASTER',
6 int_table => 'T_WJQ2_MASTER_INTERIM',
7 copy_indexes => dbms_redefinition.cons_orig_params,
8 num_errors => error_count);
9 end;
10 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:05.39
SEIANG@seiang11g> exec dbms_redefinition.finish_redef_table('SEIANG','T_WJQ2_MASTER','T_WJQ2_MASTER_INTERIM');
PL/SQL procedure successfully completed.
Elapsed: 00:00:02.38
--下面对t_wjq2_slave表进行在线重定义
SEIANG@seiang11g> exec dbms_redefinition.start_redef_table('SEIANG','T_WJQ2_SLAVE','T_WJQ2_SLAVE_INTERIM',col_mapping => 'owner owner, table_name table_name, column_name column_name',options_flag => dbms_redefinition.cons_use_pk);
PL/SQL procedure successfully completed.
Elapsed: 00:00:01.31
SEIANG@seiang11g>select count(*) from t_wjq2_slave;
COUNT(*)
----------
31434
Elapsed: 00:00:00.00
SEIANG@seiang11g>
SEIANG@seiang11g>select count(*) from t_wjq2_slave_interim;
COUNT(*)
----------
31434
Elapsed: 00:00:00.01
SEIANG@seiang11g>exec dbms_redefinition.sync_interim_table('SEIANG','T_WJQ2_SLAVE','T_WJQ2_SLAVE_INTERIM');
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.03
SEIANG@seiang11g>declare
2 error_count number:=0;
3 begin
4 dbms_redefinition.copy_table_dependents(
5 uname => 'SEIANG',orig_table => 'T_WJQ2_SLAVE',
6 int_table => 'T_WJQ2_SLAVE_INTERIM',
7 copy_indexes => dbms_redefinition.cons_orig_params,
8 num_errors => error_count);
9 end;
10 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:05.68
SEIANG@seiang11g>exec dbms_redefinition.finish_redef_table('SEIANG','T_WJQ2_SLAVE','T_WJQ2_SLAVE_INTERIM');
PL/SQL procedure successfully completed.
Elapsed: 00:00:02.60
--验证重定义结果,查看分区的情况
SEIANG@seiang11g>select table_name, partition_name from dba_tab_partitions where table_owner='SEIANG' and table_name in ('T_WJQ2_MASTER','T_WJQ2_SLAVE');
TABLE_NAME PARTITION_NAME
------------------------------ ------------------------------
T_WJQ2_MASTER P1
T_WJQ2_MASTER P2
T_WJQ2_SLAVE P1
T_WJQ2_SLAVE P2
--查看约束的情况
SEIANG@seiang11g>select owner,constraint_name,constraint_type,table_name,status from user_constraints where table_name like 'T_WJQ2%';
OWNER CONSTRAINT_NAME C TABLE_NAME STATUS
-------------------- ------------------------------ - ------------------------------ --------
SEIANG SYS_C0011660 C T_WJQ2_SLAVE ENABLED
SEIANG SYS_C0011659 C T_WJQ2_SLAVE ENABLED
SEIANG SYS_C0011658 C T_WJQ2_SLAVE ENABLED
SEIANG TMP$$_SYS_C00116580 C T_WJQ2_SLAVE_INTERIM ENABLED
SEIANG SYS_C0011656 C T_WJQ2_MASTER ENABLED
SEIANG SYS_C0011655 C T_WJQ2_MASTER ENABLED
SEIANG TMP$$_SYS_C00116560 C T_WJQ2_MASTER_INTERIM ENABLED
SEIANG TMP$$_SYS_C00116550 C T_WJQ2_MASTER_INTERIM ENABLED
SEIANG TMP$$_SYS_C00116590 C T_WJQ2_SLAVE_INTERIM ENABLED
SEIANG TMP$$_SYS_C00116600 C T_WJQ2_SLAVE_INTERIM ENABLED
SEIANG FK_T_WJQ2_SLAVE R T_WJQ2_SLAVE ENABLED
SEIANG PK_T_WJQ2_SLAVE P T_WJQ2_SLAVE ENABLED
SEIANG PK_T_WJQ2_MASTER P T_WJQ2_MASTER ENABLED
SEIANG TMP$$_PK_T_WJQ2_MASTER0 P T_WJQ2_MASTER_INTERIM ENABLED
SEIANG TMP$$_PK_T_WJQ2_SLAVE0 P T_WJQ2_SLAVE_INTERIM ENABLED
SEIANG TMP$$_FK_T_WJQ2_SLAVE0 R T_WJQ2_SLAVE DISABLED
SEIANG TMP$$_FK_T_WJQ2_SLAVE1 R T_WJQ2_SLAVE_INTERIM DISABLED
SEIANG TMP$$_TMP$$_FK_T_WJQ2_SLAVE0 R T_WJQ2_SLAVE_INTERIM DISABLED
重定义成功。
Oracle在线重定义是一种非常强大的定义工具。通过三篇文章的几个简单案例介绍了在线重定义最常用的一些流程和方法。其他一些诸如register对象和重命名的方法,在一些特定场合下有比较好的使用空间。详细的使用方法请参考另一篇博文:Oracle在线重定义之DBMS_REDEFINITION:http://blog.itpub.net/31015730/viewspace-2144516/
在使用在线重定义的时候,需要注意以下几点:
1、如果离线操作能够解决问题,就不要用在线重定义;例如一些静态数据、历史数据的归档迁移,可使用CTAS、alter table move…、或导出导入完成
2、表空间至少要留有比源表所用空间更大的剩余空间
3、在线重定义的操作过程耗时较长,但对业务的影响最小
4、要注意源表上的事务操作,如果过于频繁,可能会发生较严重的等待
应该说,Oracle在线重定义是一种平滑性能、减少锁定、提高系统整体可用性的解决方案。从操作时间和空间消耗上,在线重定义并不具有很高的优势。对于7*24小时的系统,该特性是一种不错的选择。
参考链接:
http://blog.itpub.net/11676357/viewspace-1052296/
http://www.cnblogs.com/flowerszhong/p/4535206.html
作者:SEian.G(苦练七十二变,笑对八十一难)