Oracle 在线重定义(DBMS_REDEFINITION)

Oracle 在线重定义(DBMS_REDEFINITION)

适用版本:Oracle Database 9i / 10g / 11g / 12c / 19c / 23ai 文档版本:v1.0 / 2026-07


1. 概述

在线重定义 在业务运行时重组表[1]:

用途

  • 修改表结构
  • 改变分区策略
  • 重组数据
  • 修改列类型

2. 流程

2.1 步骤

  1. 验证可重定义
  2. 创建中间表
  3. 启动重定义
  4. 同步数据
  5. 完成重定义

2.2 概念

  • 原表:业务表
  • 中间表:新结构表
  • 物化视图:同步

3. 实战

3.1 验证

BEGIN
  DBMS_REDEFINITION.CAN_REDEF_TABLE(
    uname => 'SCOTT',
    tname => 'EMPLOYEES',
    options_flag => DBMS_REDEFINITION.CONS_USE_PK
    -- CONS_USE_PK / CONS_USE_ROWID
  );
END;
/

3.2 创建中间表

CREATE TABLE employees_new (
  id NUMBER PRIMARY KEY,
  name VARCHAR2(100),
  salary NUMBER,
  hire_date DATE
)
PARTITION BY RANGE (hire_date) (
  PARTITION p2020 VALUES LESS THAN (TO_DATE('2021-01-01', 'YYYY-MM-DD')),
  PARTITION p2021 VALUES LESS THAN (TO_DATE('2022-01-01', 'YYYY-MM-DD')),
  PARTITION p_max 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, hire_date hire_date',
    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 添加依赖对象

-- 触发器、索引、约束、授权
-- 自动或手动
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 => FALSE
  );
END;
/

3.6 完成

BEGIN
  DBMS_REDEFINITION.FINISH_REDEF_TABLE(
    uname => 'SCOTT',
    orig_table => 'EMPLOYEES',
    int_table => 'EMPLOYEES_NEW'
  );
END;
/

3.7 清理

DROP TABLE employees_new;

4. 选项

4.1 CONS_USE_PK

  • 基于主键
  • 表必须有主键

4.2 CONS_USE_ROWID

  • 基于 ROWID
  • 无主键表

5. 重定义模式

5.1 完全

  • 默认
  • 全表同步

5.2 增量

BEGIN
  DBMS_REDEFINITION.START_REDEF_TABLE(
    ...,
    options_flag => DBMS_REDEFINITION.CONS_USE_PK + DBMS_REDEFINITION.CONS_MATERIALIZED
  );
END;
/

6. 中断

6.1 中止

BEGIN
  DBMS_REDEFINITION.ABORT_REDEF_TABLE(
    uname => 'SCOTT',
    orig_table => 'EMPLOYEES',
    int_table => 'EMPLOYEES_NEW'
  );
END;
/

6.2 清理

DROP TABLE employees_new;
DROP MATERIALIZED VIEW employees_new;  -- 如有

7. 应用场景

7.1 增加分区

-- 单表变分区表
BEGIN
  DBMS_REDEFINITION.START_REDEF_TABLE(...);
END;
/

7.2 修改列

-- 修改列类型
-- 中间表用新类型

7.3 表压缩

CREATE TABLE new_table ... COMPRESS FOR OLTP;

7.4 重组表

-- 降低高水位
-- 减少碎片

8. 监控

8.1 查看

SELECT * FROM dba_redefinition_tables;

8.2 进度

-- v$session_longops
SELECT 
  sid, 
  serial#,
  opname,
  sofar,
  totalwork,
  ROUND(sofar / totalwork * 100, 2) AS pct
FROM v$session_longops
WHERE opname LIKE '%REDEF%';

9. 限制

9.1 不支持

  • IOT
  • 含 LONG 列
  • 含用户定义类型
  • 物化视图容器表
  • AQ 队列表

9.2 主键要求

  • CONS_USE_PK 必须有主键
  • 否则用 CONS_USE_ROWID

10. 性能优化

10.1 并行

ALTER SESSION ENABLE PARALLEL DML;
ALTER SESSION FORCE PARALLEL DML PARALLEL 8;
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 8;

10.2 NOLOGGING

CREATE TABLE new_table NOLOGGING AS ...;

10.3 分批同步

-- 多次 SYNC
EXEC DBMS_REDEFINITION.SYNC_INTERIM_TABLE(...);

11. 常见坑与排错

11.1 ORA-12091: 物化视图存在

-- 删除依赖物化视图
DROP MATERIALIZED VIEW ...;

11.2 ORA-23539: 表正在重定义

-- 中止
EXEC DBMS_REDEFINITION.ABORT_REDEF_TABLE(...);

11.3 依赖对象错误

-- 1. ignore_errors => TRUE
-- 2. 检查 dba_redefinition_errors
SELECT * FROM dba_redefinition_errors;

12. 最佳实践

  1. 业务低峰:性能
  2. 并行:加速
  3. NOLOGGING:少 Redo
  4. 分批 SYNC:长操作
  5. 依赖对象复制:完整
  6. 监控进度:v$session_longops
  7. 测试验证:先测试
  8. 备份:失败回滚
  9. 检查错误:dba_redefinition_errors
  10. 完成后清理:中间表

13. 参考资料

[1] Oracle Database Administrator’s Guide 19c, “Online Redefinition” https://docs.oracle.com/en/database/oracle/oracle-database/19/admin/online-redefinition.html