在数据库中,我们可能会要修改数据库的逻辑或物理结构,oracle提供了一个机制能够在不严重影响表可用的情况下修改,就是在线重定义。当表在线重定义的时候,对于查询及dml语句都是可以访问的。表会有一小段时间处于exclusive模式下,时间的长短依赖与表的大小及重定义的复杂度。在线重定义要求一定数量的空闲空间,大概是表的大小的空间,要是添加列的话,还需要更多的空间。可以使用em或是dbms_redefinition包。
1在线重定义的特点
2使用dbms_redefinition在线重定义
3重定义进程的结果
4执行中间同步
5终止重定义,在报错后的清理
6在线重定义表的限制
7在线重定义一个分区
8例子
9dbms_redefinition要求的包
在线重定义的特点
在线重定义可以让你:1修改一个表或cluster的存储参数2移动一个表或culster到另一个表空间中3在表上增加,修改,删除一个或更多的列4增加或删除分区5改变分区结构5改变表的物理属性包括移动它到不同的表空间5改变物化视图日志或streams advanced queueing queue表的物理属性。6增加并行查询支持7重建表或cluster来减少碎片
8改变一个堆表到索引组织表,或反过来。9转换一个关系表到对象列,或反过来
使用dbms_redefinition
1 选择重定义方法1by key 2 by rowid
by key:选择一个主键或是伪主键来重定义,对这个方法,在转变前及转变后,表应该有相同的主键列。这个是推荐并是默认的方法。
by rowid:如果没有主键可以使用,在这个方法中,一个隐藏的列M_ROW$$被添加到重定义后的表中,在重定义后,这个列应该被删除或标记为不可以用,在索引组织表上不能用这个方法。
2通过使用can_redef_table存储过程来检查表是否可以被重定义,如果表不能在线重定义,这个存储过程就会抛出一个错误并且说明原因
3创建一个想要的逻辑和物理属性的临时表,和想要重定向的表在同一个模式下,如果是要删除一个列,那么在临时表中不要包含这些列。如果是要添加列,在临时表中加上这些列。如果是要修改列,在临时表上创建想要的属性。
对临时表来说,创建索引,约束,触发器是不需要的,在步骤6会拷贝依赖对象
4如果你在重定义一个大表,要使用并行来提高速度,执行下面的语句
alter session force parallel dml parallel degree-of-parallelism;
alter session force parallel query parallel degree-of-parallism;
5使用start_redef_table开始重定义过程,要提供:
1模式和要重定向的表名
2临时表名
3列映射的字符串
4重定向方法
5可选的,用来排序的列
6要是重定义一个分区,提供这个分区的分区名。
这个过程要拷贝数据,需要一段时间,在这其间,查询及dml仍然是可用的。
6拷贝依赖对象
方法1自动创建依赖对象
使用 copy_table_dependents存储过程来自动在临时表上创建依赖对象。这个过程也注册依赖对象,注册依赖对象使得标识这些对象及拷能自动的转换来作为过程的一部分,重定向完后,这些对象和原来的由相同的名字。
方法2 手工创建依赖对象
7执行finish_redef_table存储过程来完成重定义过程,在这个过程中,源表在exclusize模式锁定一个很小的时间。
8如果使用的rowid来重定义,你的compatible参数设置了10.1或更低,使用下面的语句来隐藏M_ROW$$列
alter table table_name set unused(m_row$$);
如果compatible是10.2或更高,这个列自动隐藏。
构造列映射字符串
在映射串中使用逗号分隔多个串,每个串用下面的格式
[expression] column_name
column_name指的是临时表的列,expression可以包含正在重定义表的列,常量,操作符,函数和方法调用等,与sql中select的规则一样。如果有expression,在重定义的时候,他的值写到临时表中,如果没有expression,就假设重定义表与临时表有一样的列名,重定向表中的列值放到临时表相同的列中。例如:
override*1.02 override_commission override重定向到override_commision中,每一个override上升2%。
如果你提供了'*'或是null在列映射字符串中,就假设所有的列被包含在临时表中,否则,只有在字符串中具体指出的列才在临时表中,映射可以使无序的。
数据转换,当映射列的时候,你可以转换数据类型,带有一些限制。
自动的创建依赖对象
可以使用copy_table_ependents存储过程来在临时表上自动创建依赖对象。通过查看num_errors输出看错误,如果ignore_errors参数被设置成true,copy_table_dependents存储过程能继续拷贝依赖的对象即使遇到错误,可以查看dba_redefinition_errors视图来看这些错误。
错误的原因包括:
1缺少系统资源
2逻辑结构的改变可以要求记录依赖对象
如果遇到错误,可以修正错误,然后再次运行copy_table_dependents存储过程。
手工创建依赖对象
如果手工创建,你必须使用register_dependent_object存储过程来注册依赖对象。
可以查看dba_redefinition_objects视图来确定哪些对象被注册了,unregister_dependent_object存储过程可以用来unregister一个正在重定义的或在临时表上的依赖对象
重定义过程的结果
下面是重定义的结果:
1原表被重定义
2依赖对象呗注册
3在原表上的索引,触发器,约束被转移到临时表上,当用户删除临时表的时候,他们一起删除。
4定义在原表上的pl/sql存储过程和游标都无效,下次使用的时候,自动重新有效。
执行中间同步
在重定向过程调用start_redef_table开始后,finish_redef_table之前,在原表上大量的dml执行是可能的。建议你阶段使用原表同步临时表。通过sync_interim_table存储过程来实现,调用这个存储过程减少finish_redef_table完成的时间。调用sync_interim_table没有次数限制。
终止在线重定义并在发生错误后的清除。
在错误发生或是要终止过程的时候,调用abort_redef_table来终止,这个存储过程删掉临时日志和表。当这个过程结束后,你删除临时表和依赖的对象。如果不调用abort_redef_table后续的重定义尝试会失败。
在线重定义表的限制
If the table is to be redefined using primary key or pseudo-primary keys (unique keys or constraints with all component columns having not null constraints), then the post-redefinition table must have the same primary key or pseudo-primary key columns. If the table is to be redefined using rowids, then the table must not be an index-organized table.
Tables that are replicated in an n-way master configuration can be redefined, but horizontal subsetting (subset of rows in the table), vertical subsetting (subset of columns in the table), and column transformations are not allowed.
The overflow table of an index-organized table cannot be online redefined independently.
Tables with BFILE
columns cannot be online redefined.
Tables with LONG
columns can be online redefined, but those columns must be converted to CLOBS
. Also, LONG RAW
columns must be converted to BLOBS
. Tables with LOB
columns are acceptable.
On a system with sufficient resources for parallel execution, and in the case where the interim table is not partitioned, redefinition of a LONG
column to a LOB
column can be executed in parallel, provided that:
The segment used to store the LOB
column in the interim table belongs to a locally managed tablespace with Automatic Segment Space Management (ASSM) enabled.
There is a simple mapping from one LONG
column to one LOB
column, and the interim table has only one LOB
column.
In the case where the interim table is partitioned, the normal methods for parallel execution for partitioning apply.
Tables in the SYS
and SYSTEM
schema cannot be online redefined.
Temporary tables cannot be redefined.
A subset of rows in the table cannot be redefined.
Only simple deterministic expressions, sequences, and SYSDATE
can be used when mapping the columns in the interim table to those of the original table. For example, subqueries are not allowed.
If new columns are being added as part of the redefinition and there are no column mappings for these columns, then they must not be declared NOT
NULL
until the redefinition is complete.
There cannot be any referential constraints between the table being redefined and the interim table.
Table redefinition cannot be done NOLOGGING
.
For materialized view logs and queue tables, online redefinition is restricted to changes in physical properties. No horizontal or vertical subsetting is permitted, nor are any column transformations. The only valid value for the column mapping string is NULL
.
Tables with materialized view logs defined on them cannot be redefined online.
You can convert a VARRAY
to a nested table with the CAST
operator in the column mapping. However, you cannot convert a nested table to a VARRAY
.
在线重定义一个分区
在10.2开始,你可以重定义一个表的分区。重定义一个表分区在下面几个方面与重定义表是不一样的。
1不必拷贝依赖对象。
2必须手工在临时表上创建逻辑索引
3列映射字符串的start_redef_table必须是null
规则:
在线重定义的机制实际上是使用的exchange partiton,因此限制也是有exchange partition的限制
No logical changes (such as adding or dropping a column) are permitted.
No changes to the partitioning method (such as changing from range partitioning to hash partitioning) are permitted.
If a global index is present, it is marked as UNUSABLE
when redefinition of any table partition is complete.
Here are the rules for defining the interim table:
If the partition being redefined is a range, hash, or list partition, the interim table must be non-partitioned.
If the partition being redefined is a range partition of a composite range-hash partitioned table, the interim table must be a hash partitioned table. In addition, the partitioning key of the interim table must be identical to the subpartitioning key of the range-hash partitioned table, and the number of partitions in the interim table must be identical to the number of subpartitions in the range partition being redefined.
If the partition being redefined is a range partition of a composite range-list partitioned table, the interim table must be a list partitioned table. In addition, the partitioning key of the interim table must be identical to the subpartitioning key of the range-list partitioned table, and the values lists of the interim table's list partitions must exactly match the values lists of the list subpartitions in the range partition being redefined.
These additional rules apply if the table being redefined is a partitioned index-organized table:
The interim table must also be index-organized.
The original and interim tables must have primary keys on the same columns, in the same order.
If key compression is enabled, it must be enabled for both the original and interim tables, with the same prefix length.
Both the original and interim tables must have overflow segments, or neither can have them. Likewise for mapping tables.
Both the original and interim tables must have identical storage attributes for any LOB columns.
例子:
表hr.admin_emp有empno,ename,job,deptno几个列,按下面的来重定义:
1新列mgr,hiredate,sal和bonus被添加进来
2新列bonus初始设置0
3deptno列增加10
4被重定义的表按empno范围分区
步骤
1验证是否可重定义
BEGIN DBMS_REDEFINITION.CAN_REDEF_TABLE('hr','admin_emp', DBMS_REDEFINITION.CONS_USE_PK); END; /
2创建临时表hr.int_admin_emp
CREATE TABLE hr.int_admin_emp (empno NUMBER(5) PRIMARY KEY, ename VARCHAR2(15) NOT NULL, job VARCHAR2(10), mgr NUMBER(5), hiredate DATE DEFAULT (sysdate), sal NUMBER(7,2), deptno NUMBER(3) NOT NULL, bonus NUMBER (7,2) DEFAULT(1000)) PARTITION BY RANGE(empno) (PARTITION emp1000 VALUES LESS THAN (1000) TABLESPACE admin_tbs, PARTITION emp2000 VALUES LESS THAN (2000) TABLESPACE admin_tbs2);
3开始重定义过程
BEGIN DBMS_REDEFINITION.START_REDEF_TABLE('hr', 'admin_emp','int_admin_emp', 'empno empno, ename ename, job job, deptno+10 deptno, 0 bonus', dbms_redefinition.cons_use_pk); END; /
4拷贝对象,自动创建触发器,索引,赋权,约束
DECLARE num_errors PLS_INTEGER; BEGIN DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS('hr', 'admin_emp','int_admin_emp', DBMS_REDEFINITION.CONS_ORIG_PARAMS, TRUE, TRUE, TRUE, TRUE, num_errors); END;
注意ignore_errors被设置true.
5查询dba_redefinition_errors视图检查是否有错误
SQL> select object_name, base_table_name, ddl_txt from DBA_REDEFINITION_ERRORS; OBJECT_NAME BASE_TABLE_NAME DDL_TXT ------------- ---------------- ------------------------------ SYS_C005836 ADMIN_EMP CREATE UNIQUE INDEX "HR"."TMP$ $_SYS_C0058360" ON "HR"."INT_A DMIN_EMP" ("EMPNO") SYS_C005836 ADMIN_EMP ALTER TABLE "HR"."INT_ADMIN_EM P" ADD CONSTRAINT "TMP$$_SYS_C 0058360" PRIMARY KEY
这些错误是因为临时表上存在的主键约束导致的,可以忽略。
6可选的,同步临时表hr.int_admin_emp
BEGIN DBMS_REDEFINITION.SYNC_INTERIM_TABLE('hr', 'admin_emp', 'int_admin_emp'); END; /
7完成重定义
BEGIN DBMS_REDEFINITION.FINISH_REDEF_TABLE('hr', 'admin_emp', 'int_admin_emp'); END; /
在这步结束的时候,表被以排他模式锁住。
8删除临时表。
dbms_redefinitin包要求的权限
Execute privileges on the DBMS_REDEFINITION
package are granted to EXECUTE_CATALOG_ROLE
. In addition to having execute privileges on this package, you must be granted the following privileges:
CREATE
ANY
TABLE
ALTER
ANY
TABLE
DROP
ANY
TABLE
LOCK
ANY TABLE
SELECT
ANY
TABLE
The following additional privileges are required to execute COPY_TABLE_DEPENDENTS
:
CREATE
ANY
TRIGGER
CREATE
ANY
INDEX