SHRINK SPACE 失败的五大前提:表空间须为 ASSM 管理(AUTO)、表必须启用行移动(ENABLED)、不能含 LONG/BFILE/函数索引/位图连接索引/物化视图主表/LOB 列、TEMP/UNDO 表空间不支持、收缩后须立即收集统计信息。

不是语法错,是前提条件没满足——缺一不可
检查表空间是否为 ASSM 管理
Oracle 只允许在自动段空间管理(ASSM)的表空间中执行 SHRINK SPACE。如果表空间是 MANUAL 段管理,命令会静默失败或报 ORA-10635。
- 查法:
SELECT segment_space_management FROM dba_tablespaces WHERE tablespace_name = 'YOUR_TBS',结果必须是AUTO - 本地管理(
LOCAL)只是基础要求,还不够;MANUAL段管理的本地表空间仍不支持 shrink - SYSTEM、SYSAUX 默认是 ASSM,但自定义表空间建库时若没指定
SEGMENT SPACE MANAGEMENT AUTO,就大概率是MANUAL
确认表已启用行移动(ENABLE ROW MOVEMENT)
没执行过 ALTER TABLE t ENABLE ROW MOVEMENT,SHRINK SPACE 就不会真正移动行,HWM 也不会下移——命令可能“成功”返回,但 DBA_SEGMENTS.BYTES 和高水位线(HWM)完全不变。
- 查法:
SELECT row_movement FROM dba_tables WHERE table_name = 'T' AND owner = 'OWNER',值必须是ENABLED - 即使表是普通堆表,只要没开行移动,
SHRINK SPACE就无效;SHRINK SPACE COMPACT同样依赖该设置 - 注意:
ENABLE ROW MOVEMENT不影响现有数据,也不需要锁表,可随时执行
排除 Oracle 明确禁止 shrink 的对象类型
有些表看似普通,但只要含特定结构,Oracle 就直接拒绝 shrink,且错误提示模糊(如 ORA-10631 或 ORA-10636),不告诉你具体拦在哪。
- 含
LONG、BFILE列的表:不支持,无例外 - 有函数索引、位图连接索引的表:
SHRINK被禁用,即使索引未被使用 - 物化视图主表(
ON PREBUILT TABLE方式创建):本质是普通表,但 Oracle 内部标记为不可 shrink - LOB 列所在的表:19c 中对表执行
SHRINK SPACE会失败(ORA-10631),哪怕 LOB 是SECUREFILE;必须单独收缩 LOB 段:ALTER TABLE t MODIFY LOB (col) (SHRINK SPACE)
别信 DBA_FREE_SPACE 查 TEMP 或 UNDO 表空间
对 TEMP 或 UNDO 表空间执行 ALTER TABLESPACE ... SHRINK SPACE,语法能过、不报错,但什么都不会发生——这是 Oracle 的硬性限制,不是你权限或配置问题。
-
TEMP:底层是 tempfile,不走段管理路径;查真实空闲用v$temp_space_header,收缩只能重建表空间 -
UNDO:撤销段生命周期由事务和保留策略控制,SHRINK不适用;报ORA-30044是正常现象 - 误操作典型:看到
DBA_TEMP_FILES.BYTES很大,以为能 shrink,结果白跑一遍;或对 undo 表空间 resize 数据文件,卡在ORA-03297
最常被忽略的一点:执行完任何 SHRINK 后,DBA_TABLES.BLOCKS 和 NUM_ROWS 可能已变,但优化器仍按旧统计信息估算执行计划——必须立刻手动执行 DBMS_STATS.GATHER_TABLE_STATS,否则后续 SQL 性能可能骤降。


















