DBMS_REDEFINITION是唯一能在线重建LOB存储结构以间接释放碎片空间的方案,适用于SHRINK SPACE不可用时;它通过新建紧凑表及LOB段并迁移数据实现,但需手动PURGE旧段才能真正释放空间。

不能直接用 DBMS_REDEFINITION 收缩 LOB 段——它不干这事;但它是唯一能在线“重建 LOB 存储结构”从而间接释放碎片空间的方案,前提是 SHRINK SPACE 不可用。
为什么 ALTER TABLE MODIFY LOB(SHRINK SPACE) 失效时才轮到 DBMS_REDEFINITION
SHRINK SPACE 是收缩 LOB 段的首选,但它有硬性限制:
-
ALTER TABLE table_name MODIFY LOB(lob_column) (SHRINK SPACE)仅对BASICFILELOB 有效,对SECUREFILE报ORA-10637 - 若表空间是
DICTIONARY管理(查DBA_TABLESPACES.EXTENT_MANAGEMENT),SHRINK 直接报错,无绕过办法 - 即使表空间是
LOCAL+AUTO,若未启用ROW MOVEMENT或含不支持类型(如BFILE),也会失败 - SHRINK 对高碎片化
BASICFILELOB 效果有限——它只清理已删除块,不重排物理存储
这时 DBMS_REDEFINITION 才成为唯一在线替代:它本质是新建一张物理紧凑的表+LOB段,把数据拷过去,旧段彻底丢弃。
DBMS_REDEFINITION 在线重建 LOB 表的实操要点
目标不是“收缩”,而是“重建存储结构”。关键动作是把 STORE AS BASICFILE 切成 STORE AS SECUREFILE(或保持 BASICFILE 但换新段),过程中自然压缩空洞。
- 必须先确认
DBMS_REDEFINITION.CAN_REDEF_TABLE('SCHEMA', 'TABLE')返回成功;若报ORA-12089(无主键)或含LONG列,立即中止 - 中间表定义中,LOB 列必须显式声明为
STORE AS SECUREFILE(哪怕原表是 BASICFILE);若只想换段不改类型,也得写STORE AS BASICFILE,否则START_REDEF_TABLE报ORA-43853 - 执行
FINISH_REDEF_TABLE后,原表名指向新段,但旧 LOB 段仍存在——必须手动DROP TABLE old_table_name PURGE,否则空间不释放 - 迁移期间 DML 性能略降(双写日志),高并发写入需预留锁等待时间;
SYNC_INTERIM_TABLE阶段若卡住,优先查v$session和v$transaction是否有未提交事务
验证收缩是否真正生效的三个必查点
别只看表大小,LOB 段空间释放与否要从底层确认:
- 查
USER_LOBS:确认SECUREFILE = 'YES'(若改了类型)且SEGMENT_NAME是新生成的段名 - 查
V$LOBSTAT:对比迁移前后BYTES_USED和BYTES_ALLOCATED比值,明显下降才说明碎片减少 - 查
DBA_SEGMENTS:用segment_name追踪旧 LOB 段是否已被PURGE,残留段会持续占用空间
最易被忽略的是 PURGE 步骤——很多人以为 FINISH_REDEF_TABLE 就完事了,结果旧 LOB 段静静躺在回收站里,占着空间还不被统计。


















