Oracle 11g 的 LOB 段不支持 SHRINK SPACE,因不满足 ASSM 管理、行移动与 HWM 下移前提;唯一可行收缩方式是 ALTER TABLE ... MOVE LOB,并需清理事务、预留空间及评估索引重建。
oracle 11g 的 lob 段不支持 shrink space,强行执行会报 ora-10631 或直接失败——这不是权限或语法问题,是底层限制。
为什么 SHRINK SPACE 对 LOB 段无效
LOB 段(BLOB、CLOB)在 Oracle 11g 中不满足 SHRINK 的前提条件:它既不是 ASSM 管理的普通堆表段,也不支持行移动(ROW MOVEMENT)与 HWM 下移的组合操作。即使你给表启用了 ENABLE ROW MOVEMENT,对含 LOB 列的表执行 ALTER TABLE ... SHRINK SPACE 仍会报错 ORA-10631: SHRINK not allowed for this object。
常见错误现象包括:
- 执行
ALTER TABLE t SHRINK SPACE后提示ORA-10631 -
DBA_SEGMENTS中 LOBSEGMENT 占用空间长期不降,即使大量DELETE了 LOB 数据 -
SELECT SUM(bytes) FROM dba_extents WHERE segment_name LIKE 'SYS_LOB%' AND owner = 'XXX'返回值远高于实际业务所需
ALTER TABLE ... MOVE 是 11g 中唯一可行的在线收缩方式
MOVE 操作能真正重写 LOB 数据,释放未用空间并降低 HWM,但它有明确副作用,必须提前评估:
- MOVE 过程中,LOB 列数据会被物理重写到新位置,旧存储块被标记为可回收
- 需确保表空间有足够空闲空间容纳临时拷贝(至少等于当前 LOB 段大小)
- MOVE 不影响索引结构,但 LOB 索引(
SYS_IL*)会自动重建,无需手动干预 - 建议加
LOB (col_name) STORE AS (ENABLE STORAGE IN ROW)子句控制是否内联存储,避免小 LOB 多余外存开销
示例命令:
ALTER TABLE orders MOVE LOB(order_doc) STORE AS (TABLESPACE users ENABLE STORAGE IN ROW);
注意:ENABLE STORAGE IN ROW 仅对 ≤ 3964 字节的 LOB 生效;超出后仍存于 LOBSEGMENT,但 MOVE 本身仍有效。
收缩前必须清理 LOB 缓存和临时区
LOB 操作常伴随大量临时段和缓存残留,尤其在 DBMS_LOB.TRIM 或批量 UPDATE 后。不清理会导致 MOVE 失败或空间无法真正释放:
- 检查是否存在未提交的 LOB 写入:
SELECT * FROM v$transaction WHERE xidusn > 0 AND used_ublk > 0 - 确认无活跃 LOB 锁:
SELECT * FROM dba_locks WHERE lock_type = 'UL' AND mode_held != 'Null' - 临时表空间压力大时,MOVE 可能卡在排序阶段——先运行
ALTER TABLESPACE temp SHRINK SPACE释放临时空间
若发现长时间未结束的 LOB 相关事务,优先用 ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE 终止,避免阻塞 MOVE。
替代方案:只收缩 LOB 索引段(适用高频更新小 LOB 场景)
如果 LOB 数据本身变动少,但索引碎片严重(如频繁 INSERT/DELETE 导致 SYS_IL* 段膨胀),可单独重建 LOB 索引:
- 查出 LOB 索引名:
SELECT index_name FROM dba_indexes WHERE table_name = 'ORDERS' AND index_type = 'LOB' - 重建命令:
ALTER INDEX SYS_IL0000102557C00003$$ REBUILD ONLINE - 该操作不影响 LOB 数据存储,但能压缩索引段、减少 I/O 开销
注意:REBUILD ONLINE 在 11g 中支持,但要求数据库处于归档模式且有足够 undo 空间;非归档模式下只能用 REBUILD 并接受短时锁表。
LOB 段空间回收不是“执行一条 shrink 就完事”的线性过程。它依赖 MOVE 的物理重写、事务清理的及时性、以及临时资源的预留——任何一环卡住,空间就停在那儿不动。最易被忽略的是:MOVE 前没检查 v$transaction,结果命令挂起数小时却无报错。


















