dbms_redefinition在线重定义需满足主键、中间表结构匹配等硬性条件,否则报ora-12089等错误;须手动建本地分区索引、预留双倍空间、分批同步并重授权限。

DBMS_REDEFINITION 能在不锁表、不停业务的前提下把普通表转成分区表,但前提是满足硬性条件——否则执行到一半会卡住或报错,比如 ORA-12089 这类错误根本不是性能问题,而是前提没达标。
表必须有主键,否则 CAN_REDEF_TABLE 直接失败
没有主键的表无法用默认方式启动重定义:START_REDEF_TABLE 会抛 ORA-12089: 不能联机重新定义无主键的表。这时有两个选择:
- 加主键(最稳妥):确保列值唯一且非空,例如
ALTER TABLE t ADD CONSTRAINT pk_t PRIMARY KEY(id); - 改用
CONS_USE_ROWID模式:调用CAN_REDEF_TABLE和START_REDEF_TABLE时显式传入DBMS_REDEFINITION.CONS_USE_ROWID,但后续无法自动同步主键约束和唯一索引,得手动重建
注意:即使加了主键,如果主键列在重定义过程中被修改(如更新、删除),SYNC_INTERIM_TABLE 可能漏数据或报错。
中间表定义必须严格匹配目标分区结构
中间表(interim table)不是“临时占位符”,它就是最终的分区表。它的 DDL 必须包含:
- 所有原表列(顺序可不同,但类型、长度、NULL 属性要兼容)
- 完整的
PARTITION BY ...子句,包括分区键、分区方法(RANGE/LIST/HASH)、每个PARTITION的VALUES LESS THAN或等效定义 - 若新增列,不能带
NOT NULL约束(否则COPY_TABLE_DEPENDENTS会失败)
常见坑:CREATE TABLE t_part (...) PARTITION BY RANGE(created) 中,created 列在原表是 DATE,但中间表误写成 VARCHAR2 —— START_REDEF_TABLE 不报错,但后续 SYNC_INTERIM_TABLE 会因隐式转换失败。
COPY_TABLE_DEPENDENTS 默认不复制主键索引为本地分区索引
很多人以为执行完 COPY_TABLE_DEPENDENTS,主键就自动变成分区索引了,其实不会。默认行为是把原全局索引照搬过去,结果新表主键仍是全局索引,失去分区裁剪优势。
正确做法是:
- 先在中间表上手动建好本地分区索引,例如:
CREATE INDEX idx_t_part_created ON t_part(created) LOCAL; - 再调用
COPY_TABLE_DEPENDENTS,并设参数copy_indexes => DBMS_REDEFINITION.cons_orig_params(或更明确地用copy_indexes => 0避免复制原索引) - 否则原主键索引会被复制为全局索引,
FINISH_REDEF_TABLE后还得手动DROP+CREATE LOCAL INDEX
空间与事务风险比想象中高
在线重定义本质是双写:原表持续写入的同时,后台不断把变更同步到中间表。这意味着:
- 需要至少等于原表大小的额外表空间(不是“稍多一点”,是“两倍”——文档明确要求)
-
SYNC_INTERIM_TABLE不是单次操作,大表建议分多次调用,避免长事务阻塞 DML;每次同步后检查DBA_REDEFINITION_STATUS视图确认无积压 - 不能用
nologging,归档压力明显增大,生产环境务必提前评估归档空间和网络带宽
最容易被忽略的是依赖对象权限——COPY_TABLE_DEPENDENTS 不复制 GRANT,重定义完成后原表名已切换,旧 GRANT 全失效,必须提前导出并重放。











