高可用之在线重定义表

来源:互联网 发布:淘宝企业注册流程 编辑:程序博客网 时间:2024/04/30 21:10

 

在高可用环境中,我们会使用在线重定义表来重新整理表,

其内部原理根据MV来实现的,类似现在原表上创建一个MV,然后一直增量刷新到数据差别最小,

完全同步->增量同步->切换完成。

可以完成:

修改表的一些参数,一些需要重组才能起效的特性,比如initrans

重组表数据,压缩空间

在线把表从一个表空间迁移到另外一个表空间

吧表从分区表转为普通表,或者普通表转为分区表

在线删除字段

二、实例

1)        创建实验用户

SQL> create user test identified bytest;

 

User created

 

SQL> grant connect,resource to test;

 

Grant succeeded

 

SQL> conn test/test

SQL> conn test/test@orcl_76

Connected to Oracle Database 11g EnterpriseEdition Release 11.2.0.1.0

Connected as test@orcl_76

2)        创建测试表,

SQL>create table t(a int,b int);

 

Tablecreated

 

declare iint;

begin

for i in1..100 loop

insertinto t values(i,100-i);

end loop;

commit;

end;

 

SQL>create table t1 (c int);

 

Tablecreated

 

SQL>

SQL>create trigger tr_t

  2     before insert or update or delete on t

  3     for each row

  4     declare

  5     PRAGMA AUTONOMOUS_TRANSACTION;--- 般情况下利用触发器禁止某些对表的更新等操作时,若记录日志,则触发器最后抛出异常时会造成日志回滚。利用自治事务可防止此点,结束时需要明确commit、ROLLBACK或执行DDL

  6     begin

  7     update t1 set c=c+1;

  8     commit;

  9     end;

 10  /

SQL>insert into c values(0);

 

insert into c values(0)

commit

SQL>insert into t values(0,0);

 

1 rowinserted

 

SQL>select * from t1;

 

              C

---------------------------------------

                   1

3)        检查可行性

给用户test 赋予dba权限

然后

SQL>exec dbms_redefinition.can_redef_table('TEST','T');

 

begindbms_redefinition.can_redef_table('TEST','T'); end;

 

ORA-12089:不能联机重新定义无主键的表 "TEST"."T"

ORA-06512:在 "SYS.DBMS_REDEFINITION", line 139

ORA-06512:在 "SYS.DBMS_REDEFINITION", line 1782

ORA-06512:在 line 2

 

SQL>exec dbms_redefinition.can_redef_table('TEST','T');

 

PL/SQLprocedure successfully completed

 

SQL>alter table t add constraint pk_t_id primary key(a);

 

Table altered

4)        创建中间表

create table t_temp (a int,b int,c int)

partition by range(a)

(partition p10 values less than(50),

partition p20 values less than (100),

partition p30 values less than (200));

5)        执行在线重定义

SQL> executedbms_redefinition.start_redef_table('TEST','T','T_TEMP','a a,b b,0 c');

 

PL/SQL procedure successfully completed

 

       101

 

 

SQL> selectobject_name,object_type,status,object_id,data_object_id from user_objects orderby 4;

 

OBJECT_NAME                                                                     OBJECT_TYPE         STATUS   OBJECT_ID DATA_OBJECT_ID

--------------------------------------------------------------------------------------------------- ------- ---------- --------------

T                                                                               TABLE               VALID        77512         77512

TR_T                                                                            TRIGGER             VALID        77513

T1                                                                              TABLE               VALID        77514         77514

PK_T_ID                                                                         INDEX               VALID        77515          77515

T_TEMP                                                                          TABLE               VALID        77516

T_TEMP                                                                          TABLE PARTITION     VALID        77517          77517

T_TEMP                                                                          TABLE PARTITION     VALID        77518          77518

T_TEMP                                                                          TABLE PARTITION     VALID        77519          77519

MLOG$_T                                                                         TABLE               VALID        77520          77520

RUPD$_T                                                                         TABLE               VALID        77521

 

查询,看到这些中间表示mv,并且一个婊mlog$_t表示一个t的快照日志,记录t正式切换前的改变日志,原理跟mv差不多,另外一个是临时表rupd$_t,这个在mv刷新时用到

SQL> selectmview_name,container_name,build_mode from user_mviesw;

 

select mview_name,container_name,build_modefrom user_mviesw

 

ORA-00942: 表或视图不存在

 

SQL> selectmview_name,container_name,build_mode from user_mviews;

 

MVIEW_NAME                     CONTAINER_NAME                 BUILD_MODE

------------------------------------------------------------ ----------

T_TEMP                         T_TEMP                         PREBUILT

6)        在新创建的表上创建主键或者非空唯一约束

SQL> alter

  2 table t_temp add constraint t_temp_pk primary key(a);

 

Tablealtered

 

创建trigger

SQL> create trigger tr_t_temp

 2      before insert or update ordelete on t

 3      for each row

 4      declare

 5      PRAGMAAUTONOMOUS_TRANSACTION;

 6      begin

 7      update t1 set c=c+1;

 8      commit;

 9      end;

 10  /

SQL> select trigger_name,status from user_triggers;

 

TRIGGER_NAME                  STATUS

------------------------------ --------

TR_T                          ENABLED

TR_T_TEMP                      ENABLED

 

这个时候插入原表一行---查看表t1,但是没有增加

SQL> insert into t values(102,1);

 

1 row inserted

 

SQL> select count(*) from t;

 

  COUNT(*)

----------

       102

 

SQL> select count(*) from t_temp;

 

  COUNT(*)

----------

       101

 

SQL> select count(*) from mlog$_t;

 

  COUNT(*)

----------

         1

 

SQL> select count(*) from rupd$_t;

 

  COUNT(*)

----------

         0

 

SQL> select c from t1;

 

                                     C

---------------------------------------

                                      4

可以看到日志增加了一行

 

7)        执行表的同步

SQL> insert into t values(103,1);

 

1 row inserted

 

SQL> commit;

 

Commit complete

 

SQL> select count(*) from t;

 

 COUNT(*)

----------

      102

 

SQL> select count(*) from t_temp;

 

 COUNT(*)

----------

      101

 

SQL> select count(*) from mlog$_t;

 

 COUNT(*)

----------

        1

 

SQL> executedbms_redefinition.sync_interim_table('TEST','T','T_TEMP');

 

PL/SQL procedure successfully completed

 

SQL> select count(*) from mlog$_t;

 

 COUNT(*)

----------

        0

 

SQL> select count(*) from t_temp;

 

 COUNT(*)

----------

      102

 

SQL> select count(*) from t;

 

 COUNT(*)

----------

      102

 

8)        执行重构完成的过程

executedbms_redefinition.finish_redef_table('TEST','T','T_TEMP');

这个过程不要操之过急,因为我在弄得时候,太急了,执行了两次,第一个没搞完,所以死了,然后我就abort

取消用dbms_redefinition.abort_redef_table(‘TEST’,’T’,’T_TEMP’)

执行完了需要删除表t_temp,这样就执行完了全部过程

三、可用性要求不高的重定义

在可用性不高的环境中一般我们可以使用move实现重定义

表:

Alter table table_name move tablespacetbs_name

表重定义之后索引等全部失效,需要重建

索引可以在线重建

Alter index index_name rebuild  tablespace tbs_name  [online]

还有合并索引

Alter Alter index index_name coalesce ---碎片化整理

索引倾斜导致索引空间增加时,小值一端的空间很难被重用,这样应该定期重建索引

以下是建议:

如果表的块已经非常热,空间合并之后,新的快可能更热,导致buffer busy的等待或者热点快问题

如果索引不是由于倾斜引起的膨胀,如果很稳定就不建议rebuild,

0 0
原创粉丝点击