Oracle 11g中SHRINK SPACE必须满足三条件:表启用ROW MOVEMENT、表空间为本地管理(LOCAL)、段空间管理为AUTO;缺一即静默失败,BYTES与HWM均不变。

Oracle 11g 下能用 SHRINK SPACE,但必须先开 ROW MOVEMENT,且表空间得是本地管理 + ASSM;否则命令不报错,但空间一丁点都不会释放。
确认表和表空间是否满足 shrink 前提条件
缺任一条件,ALTER TABLE t SHRINK SPACE 就是空转:DBA_SEGMENTS.BYTES 不变、高水位线(HWM)不动、业务还可能被锁住。
- 查表空间是否本地管理且段空间自动管理:
SELECT extent_management, segment_space_management FROM dba_tablespaces WHERE tablespace_name = 'YOUR_TS_NAME'→ 两列都必须是'LOCAL'和'AUTO' - 查表是否启用行移动:
SELECT row_movement FROM dba_tables WHERE table_name = 'T'→ 必须是'ENABLED',否则要先执行ALTER TABLE t ENABLE ROW MOVEMENT - 注意:含
LONG、BFILE列,或建了函数索引 / 位图连接索引的表,Oracle 明确禁止 shrink,且不提示具体原因
SHRINK SPACE COMPACT 和 SHRINK SPACE 的锁与行为差异
别直接上 SHRINK SPACE,高峰期容易卡死业务——它需要瞬时 X 锁,所有 DML 全阻塞;而 COMPACT 只加 RX 锁,影响小得多。
-
SHRINK SPACE COMPACT:只做数据重组(把行往前挤),不调 HWM,DBA_TABLES.BLOCKS会下降,但DBA_SEGMENTS.BYTES不变 —— 空间还没真还给表空间 -
SHRINK SPACE(无后缀):在 COMPACT 基础上立刻下调 HWM,释放物理空间,但需短暂 X 锁;适合维护窗口内执行 -
SHRINK SPACE CASCADE:连带收缩常规索引段,但对 LOB、分区子段无效,别指望它“一键全收”
分区表和 LOB 段必须单独显式 shrink
对分区表执行 SHRINK SPACE 默认只作用于整个表段头,不会触及其下任何分区或 LOB 列——你看到“成功”,其实什么都没动。
- 收缩单个分区:
ALTER TABLE t MODIFY PARTITION p202406 SHRINK SPACE CASCADE - 收缩 SECUREFILE LOB:
ALTER TABLE t MODIFY LOB (col_lob) (SHRINK SPACE) - BASICFILE LOB 在 11g 完全不支持 shrink,只能走
MOVE PARTITION+REBUILD INDEX,且需要额外空间 - 执行完任意 shrink 后,务必手动收集统计信息:
DBMS_STATS.GATHER_TABLE_STATS,否则优化器仍按旧块数估算,可能引发性能倒退
收缩后怎么验证是否真生效?
别只看 DBA_SEGMENTS.BYTES,它反映的是分配量;真正要看的是高水位线是否下降、空块是否可复用。
- 查 HWM 位置变化:
SELECT blocks, num_rows, avg_row_len FROM dba_tables WHERE table_name = 'T'——BLOCKS应明显减少 - 查段实际占用:
SELECT bytes FROM dba_segments WHERE segment_name = 'T'—— 这才是还给表空间的真实字节数 - 查空闲块可用性:
SELECT COUNT(*) FROM dba_extents WHERE segment_name = 'T' AND file_id = X AND block_id > Y(Y 是收缩前 HWM 对应块号) - 极端情况:如果
SHRINK SPACE执行后DBA_SEGMENTS.BYTES卡住不动,说明还有会话正读写该表(比如长事务未提交),得先处理事务再重试
最常被忽略的一点:shrink 不是“一键清理”,它依赖底层空间管理机制配合。表空间没开 ASSM、表没启 ROW MOVEMENT、LOB 或分区没单独处理——这些都会让操作静默失败,而你可能还在等空间降下来。











