导读:本期聚焦于Ada创作的《Oracle在线重定义表结构怎么做?Online Redefinition实战详解》,敬请观看详情。业务系统724小时运行,修改表结构时却苦于锁表时间长、影响线上交易?Oracle提供的在线重定义(Online Redefinition)功能可以解决这个问题。它基于物化视图日志机制,允许在表持续读写的同时完成列增删、分区改造、存储参数调整、表空间迁移等操作,切换瞬间仅需要极短的排他锁。本文围绕DBMS_REDEFINITION包展开,详细讲解在线重定义的适用场景、前置检查、按主键与按ROWID两种模式的具体步骤、同步与完成切换的注意事项,以及常见报错的排查思路,帮助你在生产环境安全地完成表结构重构。

在线重定义(Online Redefinition)是Oracle提供的一项高级特性,它允许DBA在表持续对外提供服务、不断有DML操作的情况下,对表结构进行深度改造。传统的ALTER TABLE操作在涉及数据重组时往往需要长时间持有锁,对于交易型核心表来说风险极高,而在线重定义把这个过程拆成了"后台拷贝数据+短暂切换"两个阶段,切换时刻只需要秒级的排他锁,业务几乎无感知。本文将从原理、步骤和实战细节三个层面完整讲解这项技术。

Oracle在线重定义表结构怎么做?Online Redefinition实战详解

一、什么场景适合使用在线重定义

在线重定义能完成的改造远不止加列删列这么简单。它本质上是在目标表上重建一份新结构,然后通过增量同步保持两边一致,因此几乎所有"需要重建表"的需求都可以用它来无感完成。常见的适用场景包括以下几类。

第一类是普通表改造为分区表。这是在线重定义最经典的应用,当一个业务表数据量增长到数亿行,查询和归档压力变大时,可以在线把它重定义为按范围或列表分区的分区表,整个过程业务不中断。第二类是表空间迁移,比如需要把表从本地管理表空间迁移到ASSM表空间,或者把数据文件挪到更高性能的存储上。第三类是结构调整,包括修改列的数据类型(例如VARCHAR2改为NUMBER)、改变列顺序、重建碎片化严重的表以回收空间、修改PCTFREE等存储参数、变更主键或去掉压缩属性等。

需要注意的是,并非所有表都能直接做在线重定义。目标表必须具备主键,或者选择基于ROWID的模式;如果表上存在物化视图日志、是物化视图容器表、属于索引组织表的某些特殊形态,都可能受限。因此在动手之前,务必先调用CAN_REDEF_TABLE过程做可行性检查。

二、在线重定义的执行步骤详解

整个流程分为五步:检查可行性、创建中间表、启动重定义、同步数据、完成切换。下面以一张名为ORDERS的业务表为例,将它重定义为按月分区的分区表。假设连接用户是BIZ,需要先授予执行DBMS_REDEFINITION的权限。

第一步先做环境准备和检查。用具备DBA角色的用户执行授权,然后验证源表是否满足在线重定义条件:

-- 授予执行权限
GRANT EXECUTE ON DBMS_REDEFINITION TO biz;
GRANT CREATE ANY TABLE, ALTER ANY TABLE, DROP ANY TABLE, LOCK ANY TABLE TO biz;
GRANT SELECT ANY TABLE TO biz;

-- 连接到业务用户后检查表是否可重定义
BEGIN
  DBMS_REDEFINITION.CAN_REDEF_TABLE(
    uname       => 'BIZ',
    tname       => 'ORDERS',
    options_flag => DBMS_REDEFINITION.CONS_USE_PK
  );
END;
/

检查通过后,第二步创建中间表。中间表就是你期望的最终结构,这里定义成按创建月份分区的分区表,列定义要与源表保持兼容:

CREATE TABLE biz.orders_interim (
  order_id     NUMBER NOT NULL,
  customer_id  NUMBER,
  amount       NUMBER(12,2),
  order_date   DATE,
  status       VARCHAR2(20),
  CONSTRAINT pk_orders_interim PRIMARY KEY (order_id)
)
PARTITION BY RANGE (order_date) (
  PARTITION p202401 VALUES LESS THAN (DATE '2024-02-01'),
  PARTITION p202402 VALUES LESS THAN (DATE '2024-03-01'),
  PARTITION p202403 VALUES LESS THAN (DATE '2024-04-01'),
  PARTITION pmax    VALUES LESS THAN (MAXVALUE)
);

第三步启动重定义任务,这是耗时最长的阶段。如果希望并行加速,可以先在会话中开启并行度,源表和中间表也可以设置并行属性。这一步执行期间,源表仍然可以被正常读写,Oracle会自动在源表上创建物化视图日志来记录增量变化:

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

BEGIN
  DBMS_REDEFINITION.START_REDEF_TABLE(
    uname        => 'BIZ',
    orig_table   => 'ORDERS',
    int_table    => 'ORDERS_INTERIM',
    col_mapping  => NULL,  -- 列名一致时可省略映射
    options_flag => DBMS_REDEFINITION.CCONS_USE_PK
  );
END;
/

第四步是可选的同步操作。由于数据拷贝期间业务仍在写入,拷贝完成后两边存在差异。FINISH_REDEF_TABLE内部会做一次最终同步,但如果拷贝持续了几个小时,业务写入量很大,建议在正式切换前手动执行一到两次SYNC_INTERIM_TABLE,把差异提前抹平,这样最终切换的锁定时间会更短:

-- 手动同步,可多次执行
BEGIN
  DBMS_REDEFINITION.SYNC_INTERIM_TABLE(
    uname      => 'BIZ',
    orig_table => 'ORDERS',
    int_table  => 'ORDERS_INTERIM'
  );
END;
/

第五步执行完成切换。这一步会短暂锁定源表,应用最后一次增量数据,然后把两张表的定义互换——源表名指向新的分区结构,中间表名持有旧表的定义,整个过程通常在几秒内完成。切换后记得重命名或重建中间表上的索引约束命名,并将新表及其分区的统计信息收集一遍:

BEGIN
  DBMS_REDEFINITION.FINISH_REDEF_TABLE(
    uname      => 'BIZ',
    orig_table => 'ORDERS',
    int_table  => 'ORDERS_INTERIM'
  );
END;
/

-- 切换完成后收集统计信息
EXEC DBMS_STATS.GATHER_TABLE_STATS('BIZ','ORDERS',CASCADE => TRUE);

三、常见问题与注意事项

首先是索引和约束的处理。START_REDEF_TABLE只会搬运数据,源表上的索引、约束、触发器、授权和统计信息并不会自动迁移到新结构上。推荐的做法是:在启动重定义之后、执行FINISH之前,在中间表上手工创建与源表一致的索引和约束,并用COPY_TABLE_DEPENDENTS过程自动复制依赖对象,这样切换瞬间业务不会因为缺少索引而性能抖动:

DECLARE
  error_count PLS_INTEGER := 0;
BEGIN
  DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(
    uname      => 'BIZ',
    orig_table => 'ORDERS',
    int_table  => 'ORDERS_INTERIM',
    copy_indexes    => DBMS_REDEFINITION.CONS_ORIG_PARAMS,
    copy_triggers   => TRUE,
    copy_constraints=> TRUE,
    ignore_errors   => TRUE,
    num_errors      => error_count
  );
  DBMS_OUTPUT.PUT_LINE('复制过程中的错误数: ' || error_count);
END;
/

其次是空间和日志问题。在线重定义相当于把表完整复制一份,需要预留至少一倍表大小的额外空间,同时会产生大量归档日志,如果数据库运行在归档模式,务必确认归档空间充足,避免撑爆磁盘导致数据库挂起。对于超大表,建议安排在业务低峰期启动START_REDEF_TABLE,并开启并行来缩短拷贝窗口。

再来看常见报错。ORA-12089表示表上已存在物化视图日志,需要先删除旧的日志再重试;ORA-12091通常是因为存在未完成的物化视图快速刷新依赖该表,可以先完成刷新或删除相关物化视图;ORA-23539和ORA-23540则说明重定义会话异常中断后残留了未清理的状态,此时需要调用ABORT_REDEF_TABLE终止本次任务,再重新开始。另外如果FINISH阶段长时间无法获得锁,多半是长事务占着源表,需要与应用侧协调kill相关会话后再执行。

最后提醒一点,主键模式和ROWID模式的选择。CONS_USE_PK基于主键同步,性能好且是首选;CONS_USE_ROWID适用于没有主键又暂时不方便加主键的表,但同步效率较低,而且切换后表中会多出一个隐藏的ROWID列。生产环境操作前,建议先在测试环境完整演练一遍流程,确认切换时间和依赖对象处理无误后再正式实施。

Oracle在线重定义DBMS_REDEFINITION表结构重构修改时间:2026-09-01 23:20:36

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。