oracle不能直接shrink space是因为其包含数据重组(rx锁)和hwm移动(x锁)两阶段,后者需独占表且阻塞dml;必须先shrink space compact再shrink space才能在线降低hwm。

能在线降低HWM,但必须分两步走:先 shrink space compact,再 shrink space;跳过 compact 直接 shrink 会锁表阻塞 DML。
为什么不能直接 shrink space?
Oracle 的 shrink space 实际包含两个阶段:第一阶段是数据重组(compact),只加 RX 锁,影响小;第二阶段是移动高水位线(HWM),需加 X 锁,会阻塞所有 DML。如果业务持续写入,直接执行 shrink space 可能卡在第二阶段,导致应用超时或事务回滚。
- 常见错误现象:
ORA-00054: resource busy and acquire with NOWAIT specified或长时间无响应 - 根本原因:HWM 移动阶段要求表上无并发修改,而生产环境很难“清场”
- ASSM 表空间是前提:非 ASSM(如 MSSM)会报
ORA-10635: Invalid segment or tablespace type
shrink space compact 能做什么、不能做什么
这个命令只做第一阶段:把散落在段中各处的数据行,通过 insert/delete 方式紧凑排列到前面的块中,但不移动 HWM,因此不释放物理空间,也不减少 BLOCKS 值。
- 优点:全程在线,对业务影响极小;不需要停应用;可随时中断重试
- 限制:必须提前执行
alter table T enable row movement,否则报ORA-10636: ROW MOVEMENT is not enabled - 副作用:启用
row movement会让依赖ROWID的触发器、物化视图日志、某些存储过程失效,建议后续运行@?/rdbms/admin/utlrp.sql编译无效对象
真正释放空间的那一步:shrink space 和 cascade
在业务低峰期执行,完成 HWM 下移和空闲块回收。加 X 锁时间取决于段大小和碎片程度,一般几秒到几分钟不等。
- 基础用法:
alter table T shrink space—— 收缩表本身,索引保持有效(这是 shrink 相比 move 的最大优势) - 带级联:
alter table T shrink space cascade—— 同时收缩主键、唯一约束对应的索引,避免后续索引重建 - 分区表支持:
alter table PT modify partition P1 shrink space cascade,适合大分区清理后单独处理 - 验证效果:执行后查
select blocks, num_rows from user_tables where table_name = 'T',BLOCKS应明显下降,且EMPTY_BLOCKS增加
容易被忽略的关键点
很多 DBA 执行完 shrink 就以为万事大吉,但以下三点常被跳过,导致效果打折或埋下隐患:
- 统计信息未更新:shrink 后
NUM_ROWS和BLOCKS已变,但优化器仍用旧统计,可能选错执行计划;务必立即执行dbms_stats.gather_table_stats - 没确认表空间类型:
select segment_space_management from dba_tablespaces where tablespace_name = (select tablespace_name from user_tables where table_name = 'T'),非AUTO类型无法 shrink - 误以为 shrink 能替代 truncate:若表已清空,
truncate table T reuse storage更快、更彻底,且无需row movement











