首页 > Oracle > Oracle 在线重定义概述。
2013
08-27

Oracle 在线重定义概述。

在线重定义表是从oracle9i开始提供的一个功能,能在线完成对一个表结构或存储的重定义,并且不影响当前应用的使用,是oracle高可用性中的一个很有用的特性。这种机制只会在特定的时候会锁表,所以在绝大部分时间表都可以出于在线使用状态
以下是在线重定义表的一些功能:
1.修改表的存储参数;
2.可以将表转移到其他表空间;
3.增加并行查询选项;4.增加或删除分区;
5.重建表以减少碎片;
6.将堆表改为索引组织表或相反的操作;
7.增加或删除一个列。
对于在线重定义,需要对象有如下权限:
调用DBMS_REDEFINITION 包需要EXECUTE_CATALOG_ROLE角色,
除此之外,还需要CREATE ANY TABLE、ALTER ANY TABLE、DROP ANY TABLE、LOCK ANY TABLE和SELECT ANY TABLE的权限。
在线重定义的运作方式:首先大家需要了解3种表的概念:
1.原始表:准备执行在线重定义操作的表
2.目标表:执行在线重定义之后的新表,比如目标表需要新增分区,增加列,改变列属性等
3.临时表:临时表的定义是和目标表一模一样的
在线重定义的方式:
基于主键(DBMS_REDEFINITION.CONS_USE_PK):默认方式
基于rowid(DBMS_REDEFINITION.CONS_USE_ROWID):不能用于索引组合表,且重定义后的表存在隐藏列M_ROW$$
推荐使用下列语句经隐含列置为UNUSED状态或删除。
ALTER TABLE TABLE_NAME SET UNUSED (M_ROW$$);
ALTER TABLE TABLE_NAME DROP UNUSED COLUMNS;
首先在执行重定义的时候,我们需要对原表进行检查是否可以执行在线重定义,调用DBMS_REDEFINITION.CAN_REDEF_TABLE()过程,如果原表不能执行在线重定义,将会有明确的错误提示,语法如下:
开始执行在线重定义,通过以上命令确定原表可以执行在线重定义操作后,然后我们就开始开始执行重定义了,不过在这之前,不要忘了建立一个中间表,其定义和目标表一致,下面我们来看执行重定义的语法:
PS:这里的原表是resource_table,中间表是target_table,这一段’OBJECT_NAME OBJECT_NAME,ID ID,TO_CHAR(ID1) ID1’是原表和中间表的字段映射,如果类型不一致的话,原表字段需要转换一下。
接下来我们来看一下完成在线定义的过程DBMS_REDEFINITION.FINISH_REDEF_TABLE,在这之前,我们可以对临时表增加触发器,索引,约束等。但必须置为disable状态。当重定义完成时,临时表上建立的触发器、索引、约束和授权将替换原表上的触发器、索引、约束和授权。临时表上disabled的约束将在重定义表上enable。语法如下:
此外还有一个同步临时表和原表数据的过程需要介绍一下,DBMS_REDEFINITION.SYNC_INTERIM_TABLE,语法如下:
COUNT(*)
———-
91573
COUNT(*)
———-
91573
SQL> select count(*) from TARGET_TABLE;
COUNT(*)
———-
91573
SQL> select count(*) from TARGET_TABLE;
COUNT(*)
———-
91573
DBMS_REDEFINITION.SYNC_INTERIM_TABLE(
uname in varchar2, —–原表所属的用户名
tname in varchar2, —–原表名
Commit complete.
int_table in varchar2 —–临时表名
);
eg:
DBMS_REDEFINITION.SYNC_INTERIM_TABLE(‘SCOTT’,’RESOURCE_TABLE’,’TARGET_TABLE’);
另外还有其他过程定义:
ABORT_REDEF_TABLE:中断在线重定义的操作,并清除过程中产生的错误信息
COPY_TABLE_DEPENDENTS:将原表上的对象复制到临时表
REGISTER_DEPENDENT_OBJECTS:注册临时表上的对象(eg:索引,触发器)名称
下面给各位简单的演示下:
1. 首先建立原表,目标表

2. 在原表没有主键的情况下,我们对原表检查一下是否可以用主键的方式执行在线重定义,这里很明显的说了原表没有主键,不能通过主键方式。

3. 如果这里我们通过rowid的方式来在线重定义就没有问题,不过我们还是先用主键的方式测试一下。我们先建立一个主键,然后通过主键的方式测试一下表是否可以,我们可以看到resource_table现在可以通过主键执行在线重定义了

5. 此时我们开始对表通过主键方式进行在线重定义,此时我们可以看到系统创建了一个和我们临时表一样的物化视图,我们可以看到此时临时表和原表的数据一模一样
6. 此时我们往原表resource_table插入一条数据,先不提交,查看一下原表和临时表的条数,可以看到原表已经表临时表多了一条,因为同一个session相当于有隐式的提交。

7. 现在打开另一个窗口,不要在本窗口执行完成在线重定义的操作,这里我新建的窗口,原表和临时表数据一样,说明上一步的dml操作还未提交,但我执行完成在线重定义这个操作就阻塞了
8. 回到原始的窗口,执行commit之后,我们同步一下原表和临时表的数据,同步完成后,我们可以看到临时表和目标表上的数据已经一致,同步过程不是必须的,但是当我们执行完成重定义操作的时候,可以大大节省我们的时间
9. 最后我们完成在线重定义的工作,此时我们查看视图已经被删掉了。相关的日志表也drop掉了
10. 此时我们看索引已经交换到resource_table 上了,而且索引是生效的状态,resource_table的表结构已经变化,主键已经不存在,resource_table表交换成功
11. 然后我们可以删掉临时表
rowid方式这里就不作演示了。大家自己试验去吧。另外可以重定义分区,这里也不做演示了
最后编辑:
作者:Jerry
一个积极向上的小青年,热衷于分享--Focus on DB,BI,ETL