LOB字段在线重定义需禁用行内存储、显式分区、用COPY_TABLE_DEPENDENTS拷贝依赖项并校准表空间,否则报ORA-12083/ORA-14097。
LOB字段导致DBMS_REDEFINITION报ORA-12083或ORA-14097
直接用dbms_redefinition.start_redef_table对含lob的分区表做在线重定义,大概率失败。根本原因是lob列默认和基表共用段(enable storage in row),而重定义过程要求lob必须独立存储且与目标表分区严格对齐。
实操建议:
- 确认LOB是否启用行内存储:
SELECT column_name, in_row FROM dba_lobs WHERE table_name = 'YOUR_TABLE';若in_row = 'YES',必须先禁用 - 执行
ALTER TABLE your_table MODIFY LOB (lob_col) (DISABLE STORAGE IN ROW),否则重定义时LOB段无法正确映射到新分区结构 - 禁用后需触发一次全表更新(哪怕只改一个非LOB字段),强制将现有LOB数据移出行内——否则旧数据仍卡在行内,后续分区切换会出错
LOB段必须显式指定PARTITIONING_TYPE并匹配主表分区策略
DBMS_REDEFINITION.CONSULT_REDEF_TABLE不会自动推导LOB段的分区方式。即使主表是RANGE分区,LOB段默认仍是NON-PARTITIONED,这会导致FINISH_REDEF_TABLE阶段报ORA-14097(分区不匹配)。
实操建议:
- 建中间表时,LOB列必须带
STORE AS SECUREFILE(或BASICFILE)+ 显式分区子句,例如:lob_col CLOB STORE AS SECUREFILE (PARTITION BY RANGE (partition_key) (...)) - LOB分区键必须与主表分区键完全一致,包括列名、数据类型、顺序;哪怕只是多一个
TO_DATE包装,也会被判定为不兼容 - 若主表用
INTERVAL分区,LOB段不能直接写INTERVAL,得先建好所有预期分区(用ADD PARTITION),再启动重定义
DBMS_REDEFINITION.SYNC_INTERIM_TABLE对LOB分区无效
同步中间表时,SYNC_INTERIM_TABLE只会复制DML变更,但不会迁移已存在的LOB数据块位置。如果原表LOB数据量大,中间表的LOB段实际仍指向原段地址,导致FINISH_REDEF_TABLE后查询返回空或乱码。
实操建议:
- 跳过
SYNC_INTERIM_TABLE,改用COPY_TABLE_DEPENDENTS并设copy_indexes => DBMS_REDEFINITION.CONS_ORIG_PARAMS,它会重建LOB索引并重新分配段 - 确保
COPY_TABLE_DEPENDENTS的num_errors参数设为足够大(如999),否则LOB段创建失败会被静默忽略 - 执行完
COPY_TABLE_DEPENDENTS后,立刻查dba_lobs确认segment_name已更新为中间表对应的LOB段名,而非原表名
FINISH_REDEF_TABLE后LOB段未自动继承主表表空间
即使中间表LOB指定了TABLESPACE users,FINISH_REDEF_TABLE完成后,新表的LOB段可能回退到默认表空间(如SYSTEM),尤其当用户默认表空间不是LOB指定表空间时。
实操建议:
- 重定义前用
ALTER USER your_user DEFAULT TABLESPACE your_ts临时切到目标表空间,避免隐式回退 - 完成
FINISH_REDEF_TABLE后,立刻执行:ALTER TABLE your_table MOVE LOB(lob_col) STORE AS (TABLESPACE your_ts),强制迁移LOB段 - 注意MOVE操作会锁表,需安排窗口;若想在线,得配合
DBMS_LOB.COPY手动分批迁移,但代价远高于停机MOVE
LOB段的存储映射不是声明即生效,而是依赖重定义各阶段的显式动作链:禁用行内存储 → 强制数据出行 → 中间表显式分区 → 依赖项完整拷贝 → 完成后主动校准表空间。漏掉任意一环,表面成功,实际LOB访问就出问题。










