oracle 19c中非分区表转分区表无法直接alter table实现,必须用dbms_redefinition在线重定义,因其支持无锁、不中断dml、可回退,且要求源表有主键或唯一约束。
oracle 19c 中非分区表转分区表,无法真正“零停机”,但可通过在线重定义(dbms_redefinition)实现业务几乎无感的平滑切换——关键在于避免锁表、不中断dml、且全程可回退。
为什么不能直接 ALTER TABLE ... PARTITION BY?
Oracle 不允许对已有数据的非分区表直接添加分区逻辑。执行类似 ALTER TABLE t ADD PARTITION 或 MODIFY PARTITION 的语句会报错 ORA-14006: invalid partition name 或 ORA-14511: cannot perform operation on a partitioned object。底层机制决定:分区属性是表创建时即固化在数据字典中的结构性元信息,不可原地变更。
常见错误现象包括:
- 误用
CREATE TABLE AS SELECT+ 重命名,导致中间期表名冲突或应用报ORA-00942: table or view does not exist - 手动导出导入(expdp/impdp)期间应用持续写入,造成数据丢失
- 未校验依赖对象(如索引、约束、物化视图),迁移后查询报错或性能骤降
DBMS_REDEFINITION 是唯一安全路径
该包通过构建影子表(interim table)、同步增量变更、原子切换三阶段完成在线重定义,全程不阻塞 DML,且支持回滚到原始状态。前提是源表必须有主键或唯一约束(用于 ROWID 映射)。
实操要点:
- 目标分区表结构需提前设计好:例如按
CREATE_TIME范围分区,使用INTERVAL自动扩展 - 调用
DBMS_REDEFINITION.CAN_REDEF_TABLE验证兼容性,失败则需先清理物化视图日志或禁用触发器 - 启动重定义时指定
options_flag => DBMS_REDEFINITION.CONS_USE_PK,强制用主键而非 ROWID 同步,避免 ROWID 变化引发数据错位 - 增量同步阶段频繁执行
DBMS_REDEFINITION.SYNC_INTERIM_TABLE(建议每5–10分钟一次),控制影子表延迟在秒级内
切换前必须处理的依赖项
在线重定义不会自动迁移索引、约束、权限、统计信息或外键引用。遗漏会导致切换后性能崩塌或应用异常。
关键动作:
- 原表上的普通索引需在影子表上重建为本地分区索引(
LOCAL),全局索引(GLOBAL)需显式指定UPDATE GLOBAL INDEXES参数 - 外键约束必须在重定义完成后手动重建,否则
ALTER TABLE ... ENABLE CONSTRAINT会因参照完整性校验失败而卡住 - 统计信息不能复用:切换后立即执行
DBMS_STATS.GATHER_TABLE_STATS,否则优化器仍走全表扫描 - 应用连接池中若缓存了表元数据(如 Hibernate 的
hibernate.hbm2ddl.auto=validate),需重启或刷新元数据缓存
最容易被忽略的陷阱:物化视图和审计策略
如果源表被物化视图日志(MATERIALIZED VIEW LOG)跟踪,或启用了细粒度审计(DBMS_FGA.ADD_POLICY),DBMS_REDEFINITION 会静默失败或产生不一致数据。
务必在开始前确认:
- 查询
USER_MVIEW_LOGS,若有记录,先DROP MATERIALIZED VIEW LOG ON t - 检查
DBA_AUDIT_POLICIES,临时禁用相关审计策略,切换完成后再启用 - 重定义期间禁止对源表执行
FLASHBACK TABLE或FLASHBACK QUERY,否则可能读到影子表未同步的旧数据
真正的难点不在语法操作,而在于对整个依赖生态的识别与闭环处理——哪怕漏掉一个物化视图日志,都可能导致下游报表数据偏差,且问题延迟暴露。











