能,但必须分清场景:纯换表空间用dbms_redefinition.redef_table一步到位;若同时改分区、加列、调索引等逻辑结构,必须退回四步法(can_redef_table→start_redef_table→copy_table_dependents→finish_redef_table)。
能,但必须分清场景:纯换表空间用 dbms_redefinition.redef_table 一步到位;若同时改分区、加列、调索引等逻辑结构,必须退回四步法(can_redef_table→start_redef_table→copy_table_dependents→finish_redef_table)。
什么时候该用 REDEF_TABLE 而不是四步流程?
它只处理存储层变更,不碰表定义本身。满足以下任一条件,就适合单步执行:
- 只想把表(含其索引、LOB列)从
USERS换到NEW_TBS - 只想开启/关闭表级压缩(如
ROW STORE COMPRESS BASIC) - 只想把 LOB 列从
BASICFILE改成SECUREFILE
一旦你顺手在同一次操作里加了字段、改了分区键、或想让主键索引变成本地分区索引,REDEF_TABLE 就会静默忽略——不报错,也不生效。
CAN_REDEF_TABLE 返回成功 ≠ 真能重定义成功
这个函数只检查硬性限制(比如表是不是 SYS 下的、有没有 REF 类型),但真正卡住你的常是这些隐性问题:
- 源表有未提交事务 →
START_REDEF_TABLE会挂住等待,查v$session和v$transaction确认 - 中间表建在目标表空间,但该表空间最大连续空闲块
dba_free_space.bytes不够预估新表大小 →SYNC_INTERIM_TABLE报ORA-01653 - 原表主键列用了
SYSTIMESTAMP默认值,或触发器里写了SEQUENCE.NEXTVAL→START_REDEF_TABLE可能不报错,但同步后数据不一致
中间表建错的三个高频坑
中间表不是“原表 CREATE TABLE AS SELECT”就能糊弄过去。类型对齐必须严格:
-
VARCHAR2(100)和VARCHAR2(100 CHAR)视为不一致,START_REDEF_TABLE直接报ORA-14197 - 分区键列(如
ORDER_DATE)不能加NOT NULL约束,哪怕原表该列非空——中间表加了就失败 - 别手动建索引、约束、触发器。这些全交给
COPY_TABLE_DEPENDENTS处理,自己先建反而导致 COPY 阶段报ORA-14098(索引不匹配)
MOVE PARTITION ONLINE 和在线重定义不是一回事
如果你只动分区(比如把 P_202401 迁到新表空间),优先用 ALTER TABLE ... MOVE PARTITION ... ONLINE UPDATE INDEXES ONLINE:
- 它不走
DBMS_REDEFINITION,锁粒度更细,DML 不阻塞 - 但
ONLINE对 LOB 分区无效,会报ORA-14647,必须拆成两步:先主数据迁移,再单独处理 LOB - 迁移后统计信息不会自动更新,
DBA_TAB_PARTITIONS.NUM_ROWS变成NULL,得立刻跑DBMS_STATS.GATHER_TABLE_STATS(... GRANULARITY => 'PARTITION')
最后那把锁的时间其实可控,但容易被低估——尤其在大表上,FINISH_REDEF_TABLE 那一刻的 DDL 锁虽短,却可能卡住正在跑的长查询或批处理作业,得提前协调窗口。











