12c仍需用DBMS_REDEFINITION做在线重定义,因其支持复杂结构(虚拟列、LOB、多索引等),而ALTER TABLE MODIFY PARTITION BY限制多、兼容性差,且重定义后须手动收集统计信息。
直接结论:12c 仍需用 dbms_redefinition 做在线重定义,除非你满足 alter table ... modify partition by ... online 的全部限制 —— 但多数生产场景不满足。
Oracle 12c 确实新增了 ALTER TABLE ... MODIFY PARTITION BY 语法,但它不是万能替代方案。真正稳定、可控、兼容复杂结构(如含虚拟列、自增触发器、多索引、LOB 列)的在线转换,仍得靠 DBMS_REDEFINITION。
为什么不能直接用 ALTER TABLE MODIFY?
该语法表面简洁,但实际踩坑密集:
-
ALTER TABLE ... MODIFY PARTITION BY RANGE仅支持RANGE分区,不支持LIST、HASH或INTERVAL; - 必须指定所有分区键列,且这些列不能是
GENERATED ALWAYS AS虚拟列(比如你的TOTAL_AMOUNT); - 若原表有
NOT NULL约束但未设DEFAULT,而新分区键列允许空值,会报ORA-14097: column type or size mismatch; -
UPDATE INDEXES子句对全局索引要求严格:若原表有唯一约束依赖的全局索引,必须显式列出并确保其可重建,否则ORA-14098: index mismatch; - 不兼容含
ROWID伪列引用或物化视图日志的表。
DBMS_REDEFINITION 启动前必做检查
别跳过 CAN_REDEF_TABLE —— 它不报错 ≠ 表就真适合重定义:
- 执行
EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE('SZR', 'CUSTOMER_ORDERS');,成功只说明基础结构合规; - 手动确认:表在
SZR用户下、有主键(ORDER_ID)、无SYSTIMESTAMP或SEQUENCE.NEXTVAL默认值(你的触发器没问题,但默认值写法要避开); - 检查依赖:若有
REF类型列、高级队列表、审计策略,COPY_TABLE_DEPENDENTS可能失败,需提前禁用; - 预留空间:临时表 + 原表数据 ≈ 2×原表大小,且
TEMP表空间也要够(排序/同步时用)。
中间表(interim table)建表的关键细节
中间表不是简单复制结构,它决定最终分区形态和兼容性:
- 必须与原表同用户、同表空间(除非你明确想迁移),字段名/类型/长度/NULL 性必须完全一致(连
VARCHAR2(120)和VARCHAR2(120 CHAR)都算不一致); - 分区键列(如
ORDER_DATE)不能加NOT NULL约束(除非原表也强制非空),否则START_REDEF_TABLE会报ORA-14197: partition key column cannot be NOT NULL; - 索引、约束、触发器不在此建 —— 全部由
COPY_TABLE_DEPENDENTS同步,自己建反而导致冲突; - 示例中间表语句(注意
PARTITION BY RANGE和分区键类型匹配):CREATE TABLE SZR.CUSTOMER_ORDERS_INT ( ORDER_ID NUMBER PRIMARY KEY, ORDER_DATE DATE NOT NULL, CUSTOMER_ID NUMBER NOT NULL, CUSTOMER_NAME VARCHAR2(120), PRODUCT_CODE VARCHAR2(50), QUANTITY NUMBER(8), UNIT_PRICE NUMBER(12,2), TOTAL_AMOUNT NUMBER(14,2) GENERATED ALWAYS AS (QUANTITY * UNIT_PRICE) VIRTUAL, ORDER_STATUS VARCHAR2(20) DEFAULT 'PENDING', CREATED_BY VARCHAR2(60) ) PARTITION BY RANGE (ORDER_DATE) ( PARTITION P_2023 VALUES LESS THAN (DATE '2024-01-01'), PARTITION P_2024 VALUES LESS THAN (DATE '2025-01-01'), PARTITION P_2025 VALUES LESS THAN (DATE '2026-01-01'), PARTITION P_MAX VALUES LESS THAN (MAXVALUE) );
SYNC_INTERIM_TABLE 不是“一键刷新”,而是增量同步开关
很多人以为调一次 SYNC_INTERIM_TABLE 就完事,其实它只是触发一次 DML 变更捕获:
- 重定义启动后,原表任何
INSERT/UPDATE/DELETE都会写入内部物化视图日志; -
SYNC_INTERIM_TABLE把日志里积压的变更应用到中间表 —— 所以高并发写入场景,需在FINISH_REDEF_TABLE前多次调用,避免最后一步锁太久; - 典型节奏:
START_REDEF_TABLE→ 等首次全量同步完成(查DBA_REDEFINITION视图)→ 应用业务低峰期调SYNC_INTERIM_TABLE→ 再次SYNC_INTERIM_TABLE→FINISH_REDEF_TABLE; - 如果漏掉某次同步,
FINISH_REDEF_TABLE会卡住并报ORA-14402: updating partition key column would cause a partition change—— 这说明有未同步的跨分区更新。
最易被忽略的一点:重定义完成后,原表的统计信息不会自动继承到新分区表。必须手动执行 DBMS_STATS.GATHER_TABLE_STATS,否则查询计划可能严重劣化 —— 尤其当分区数据倾斜时,CBO 很可能选错分区裁剪路径。


















