Oracle 在线重定义(DBMS_REDEFINITION)
Oracle 在线重定义(DBMS_REDEFINITION)
适用版本:Oracle Database 9i / 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07
1. 概述
在线重定义(DBMS_REDEFINITION) 允许在表保持在线可用的情况下修改结构[1]:
典型场景:
- 修改表结构(添加/删除列)
- 修改分区策略
- 修改存储属性
- 重组表(消除碎片)
- 修改约束
2. 在线重定义流程
1. 验证表是否可重定义
2. 创建中间表(新结构)
3. 启动重定义
4. 同步数据(可选)
5. 完成重定义
6. 删除中间表
3. 操作步骤
3.1 验证可重定义
-- 验证表是否可重定义
BEGIN
DBMS_REDEFINITION.CAN_REDEF_TABLE(
uname => 'scott',
tname => 'employees',
options_flag => DBMS_REDEFINITION.CONS_USE_PK
);
END;
/
-- options_flag:
-- CONS_USE_PK: 使用主键
-- CONS_USE_ROWID: 使用 ROWID(无主键时)
3.2 创建中间表
-- 创建新结构的中间表
CREATE TABLE scott.employees_new (
id NUMBER PRIMARY KEY,
name VARCHAR2(100),
salary NUMBER,
dept_id NUMBER,
create_time DATE DEFAULT SYSDATE
) TABLESPACE users
PARTITION BY RANGE (create_time) (
PARTITION p2026 VALUES LESS THAN (TO_DATE('2027-01-01','YYYY-MM-DD')),
PARTITION p2027 VALUES LESS THAN (TO_DATE('2028-01-01','YYYY-MM-DD')),
PARTITION pmax VALUES LESS THAN (MAXVALUE)
);
3.3 启动重定义
BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE(
uname => 'scott',
orig_table => 'employees',
int_table => 'employees_new',
col_mapping => 'id id, name name, salary salary, dept_id dept_id, SYSDATE create_time',
options_flag => DBMS_REDEFINITION.CONS_USE_PK
);
END;
/
3.4 同步数据(可选)
-- 在重定义过程中同步增量数据
BEGIN
DBMS_REDEFINITION.SYNC_INTERIM_TABLE(
uname => 'scott',
orig_table => 'employees',
int_table => 'employees_new'
);
END;
/
3.5 复制依赖对象
-- 自动复制依赖对象(索引、约束、触发器等)
DECLARE
num_errors PLS_INTEGER;
BEGIN
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(
uname => 'scott',
orig_table => 'employees',
int_table => 'employees_new',
copy_indexes => DBMS_REDEFINITION.CONS_ORIG_PARAMS,
copy_triggers => TRUE,
copy_constraints => TRUE,
copy_privileges => TRUE,
ignore_errors => TRUE,
num_errors => num_errors
);
DBMS_OUTPUT.PUT_LINE('Errors: ' || num_errors);
END;
/
-- 查看错误
SELECT object_name, base_table_name, ddl_txt
FROM dba_redefinition_errors;
3.6 完成重定义
-- 完成重定义(短暂锁表)
BEGIN
DBMS_REDEFINITION.FINISH_REDEF_TABLE(
uname => 'scott',
orig_table => 'employees',
int_table => 'employees_new'
);
END;
/
3.7 清理
-- 删除中间表
DROP TABLE scott.employees_new PURGE;
4. 重定义选项
4.1 使用主键
options_flag => DBMS_REDEFINITION.CONS_USE_PK
4.2 使用 ROWID
-- 无主键时
options_flag => DBMS_REDEFINITION.CONS_USE_ROWID
4.3 列映射
-- 简单映射
col_mapping => 'id id, name name, salary salary'
-- 转换
col_mapping => 'id id, UPPER(name) name, salary*1.1 salary'
-- 添加新列
col_mapping => 'id id, name name, SYSDATE create_time'
5. 重定义分区表
5.1 非分区转分区
-- 中间表为分区表
CREATE TABLE scott.employees_new (...)
PARTITION BY RANGE (hire_date) (...);
-- 重定义
BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE(
uname => 'scott',
orig_table => 'employees',
int_table => 'employees_new',
col_mapping => NULL -- 列名相同可省略
);
END;
/
5.2 分区策略变更
-- 从 RANGE 转为 HASH
CREATE TABLE scott.employees_new (...)
PARTITION BY HASH (id) PARTITIONS 8;
6. 监控重定义
6.1 查看进度
-- 查看重定义进度
SELECT
sid,
serial#,
opname,
target,
sofar,
totalwork,
time_remaining
FROM v$session_longops
WHERE opname LIKE '%REDEFINITION%';
6.2 查看错误
SELECT * FROM dba_redefinition_errors;
6.3 查看对象
SELECT * FROM dba_redefinition_objects;
7. 中止重定义
-- 中止重定义
BEGIN
DBMS_REDEFINITION.ABORT_REDEF_TABLE(
uname => 'scott',
orig_table => 'employees',
int_table => 'employees_new'
);
END;
/
-- 删除中间表
DROP TABLE scott.employees_new PURGE;
8. 多租户中的重定义
8.1 PDB 中重定义
-- 切换到 PDB
ALTER SESSION SET CONTAINER = hrpdb;
-- 执行重定义(同上)
9. 常见坑与排错
9.1 ORA-12091: 表不能在线重定义
修复:
-- 1. 检查主键
SELECT constraint_name FROM dba_constraints
WHERE table_name='EMPLOYEES' AND constraint_type='P';
-- 2. 使用 ROWID 模式
options_flag => DBMS_REDEFINITION.CONS_USE_ROWID
9.2 ORA-23539: 表正在重定义
修复:
-- 1. 中止
BEGIN
DBMS_REDEFINITION.ABORT_REDEF_TABLE(
uname => 'scott',
orig_table => 'employees',
int_table => 'employees_new'
);
END;
/
-- 2. 重新开始
9.3 复制依赖对象失败
修复:
-- 1. 查看错误
SELECT * FROM dba_redefinition_errors;
-- 2. 手动创建
CREATE INDEX idx_emp_name ON scott.employees_new(name);
-- 3. 重新执行 COPY_TABLE_DEPENDENTS
9.4 性能问题
修复:
-- 1. 在低峰期执行
-- 2. 使用并行
ALTER SESSION ENABLE PARALLEL DML;
-- 3. 分批同步
BEGIN
DBMS_REDEFINITION.SYNC_INTERIM_TABLE(...);
END;
/
9.5 物化视图日志残留
修复:
-- 重定义完成后清理
DROP MATERIALIZED VIEW LOG ON scott.employees;
10. 最佳实践
- 生产用在线重定义:零停机
- 低峰期执行:减少影响
- 验证可重定义:CAN_REDEF_TABLE
- 使用主键模式:性能更好
- 分批同步:减少锁
- 复制依赖对象:保留索引约束
- 监控进度:v$session_longops
- 测试验证:先在测试库演练
- 保留中间表:应急回滚
- 完成后再清理:避免误删
11. 参考资料
[1] Oracle Database Administrator’s Guide 19c, “Online Table Redefinition” https://docs.oracle.com/en/database/oracle/oracle-database/19/admin/
[2] Oracle Database PL/SQL Packages and Types Reference 19c, “DBMS_REDEFINITION” https://docs.oracle.com/en/database/oracle/oracle-database/19/arpls/