Oracle分区表在线加字段不能直接ALTER TABLE,因会阻塞DML且可能触发ORA-14048错误;DBMS_REDEFINITION是唯一官方支持的不锁表方案,需正确设置col_mapping、options_flag和part_name参数,并注意中间表同表空间、全局索引重建等细节。
分区表在线加字段为什么不能直接 ALTER TABLE
因为 oracle 对分区表执行 alter table ... add column 时,若表启用了行移动(enable row movement)且存在全局索引,操作会阻塞 dml;更关键的是,某些版本(如 12c 早期)对带 interval 分区或引用分区的表,直接加字段可能触发 ora-14048:*partition maintenance operation may not be combined with other operations*。这不是语法错,是 oracle 内部锁和元数据变更的限制。
- 直接 DDL 修改分区表结构,在高并发写入场景下极易卡住 DML,实际等于“逻辑停机”
-
DBMS_REDEFINITION是唯一被 Oracle 官方认证支持的、真正不阻塞 DML 的在线重定义方案 - 它本质是建影子表 → 同步数据 → 切换命名 → 清理,全程原表可读可写
DBMS_REDEFINITION.START_REDEF_TABLE 参数怎么选才不翻车
最关键的三个参数是 col_mapping、options_flag 和 part_name。漏设或误设会导致同步失败、数据丢失或分区信息丢失。
-
col_mapping必须显式列出所有列(包括新增字段),不能用*—— 否则新表会丢掉原表的虚拟列、默认值、NOT NULL 约束 -
options_flag => DBMS_REDEFINITION.CONS_USE_PK最安全;若无主键,必须用CONS_USE_ROWID,但后续校验需额外跑DBMS_REDEFINITION.CONS_VALIDATE - 对单个分区做重定义(比如只改最近一个
MONTH_202404),必须传part_name => 'MONTH_202404',否则报ORA-14155:*missing PARTITION or SUBPARTITION keyword*
示例片段:
DBMS_REDEFINITION.START_REDEF_TABLE( uname => 'SCOTT', orig_table => 'SALES', int_table => 'SALES_INT', col_mapping=> 'ID ID, AMOUNT AMOUNT, NEW_COL ''Y''', options_flag => DBMS_REDEFINITION.CONS_USE_PK );
在线重定义后全局索引失效怎么办
重定义完成切换(FINISH_REDEF_TABLE)后,原表上的全局索引会自动变为 UNUSABLE,查询走不到,但 DML 仍能执行(Oracle 自动转为全表扫描)。这不是 bug,是机制设计。
- 必须在
FINISH_REDEF_TABLE后立刻重建:用ALTER INDEX idx_name REBUILD ONLINE - 如果索引带分区,要逐个子分区 rebuild,或直接
ALTER INDEX ... REBUILD PARTITION p1 ONLINE - 千万别等第二天再处理——业务慢查会集中爆发,且
UNUSABLE索引无法被统计信息收集覆盖
验证命令:SELECT index_name, status FROM dba_indexes WHERE table_name = 'SALES';,状态必须是 VALID。
为什么中间表(int_table)一定要和原表同属一个表空间
不是语法强制,但跨表空间会引发两个隐蔽问题:一是 COPY_TABLE_DEPENDENTS 复制约束/索引时,目标对象可能落在错误位置;二是重定义过程中 Oracle 内部用到的物化日志(MLOG$)表,若不在同一表空间,SYNC_INTERIM_TABLE 可能因权限或配额失败,报 ORA-12008 或 ORA-01652。
- 创建中间表前,先查:
SELECT default_tablespace FROM dba_users WHERE username = 'SCOTT'; - 显式指定表空间:
CREATE TABLE sales_int (...) TABLESPACE users; - 别依赖用户默认表空间——有些环境 default_tablespace 是
SYSTEM,重定义过程写日志会直接炸
SYNC_INTERIM_TABLE 的调用频率——数据量大时,每隔 5 分钟手动 sync 一次,比堆满内存再一次性同步更稳。










