ALTER TABLE ... SHRINK SPACE 报 ORA-10636 是因未启用行移动,必须先执行 ENABLE ROW MOVEMENT;SHRINK SPACE COMPACT 仅重组数据并加 RX 锁,不降 HWM;完整 SHRINK SPACE 还需 X 锁以降 HWM 并释放空间;CASCADE 可连带收缩相关索引;IOT、含 LONG 列、Flashback Data Archive 表等不支持 shrink;shrink 不减小数据文件物理大小,需额外 RESIZE;收缩后须 gather stats 更新 BLOCKS 值。

SHRINK SPACE 不能直接“缩文件”,只能收缩段(表/索引),且必须分步满足硬性前提,否则必然报 ORA-10636 或 ORA-10637。
为什么 ALTER TABLE ... SHRINK SPACE 总报 ORA-10636?
这不是权限或空间问题,而是表没开行移动——ENABLE ROW MOVEMENT 是强制前置条件。
- 必须先执行:
ALTER TABLE table_name ENABLE ROW MOVEMENT - 该语句是 DDL,隐式提交,不可回滚
- 启用后,
UPDATE可能触发更多 UNDO/REDO;高并发写场景要评估风险 - 所有基于
ROWID的触发器(如审计类)必须提前DISABLE,否则 shrink 会失败
SHRINK SPACE COMPACT 和 SHRINK SPACE 有什么区别?
两者作用阶段不同,锁粒度和业务影响差异极大:
-
SHRINK SPACE COMPACT:只做数据重组(insert/delete 移动行),加 RX 锁(行级),不影响 DML,但 HWM 不降、空间不释放 -
SHRINK SPACE(无参数):完成 COMPACT + 调整 HWM + 释放空闲块,第二阶段需加 X 锁(全表阻塞),DML 会挂起 -
SHRINK SPACE CASCADE:在上一条基础上,连带收缩该表所有相关索引(含分区索引),等效于对每个索引单独执行SHRINK SPACE
业务高峰期建议拆成两步:SHRINK SPACE COMPACT 先整理碎片,低峰期再补 SHRINK SPACE 释放空间。
哪些对象根本不能用 SHRINK SPACE?
不是所有表都支持——Oracle 有硬性限制,不满足直接报错,不依赖统计信息或空间状态:
- 非堆组织表:
IOT、外部表、临时表、物化视图日志表 - 含
LONG列的表(哪怕全 NULL 也不行) - 启用
Flashback Data Archive的表 - 分区表必须指定分区:
ALTER TABLE t SHRINK SPACE PARTITION p1,不能直接 shrink 整个表 - 必须位于
ASSM(自动段空间管理)表空间,查证命令:SELECT segment_space_management FROM dba_tablespaces WHERE tablespace_name = 'YOUR_TS'
收缩完空间还在操作系统里?这是正常的
SHRINK SPACE 只重排段内数据块、下压 HWM,不会缩小数据文件物理大小:
-
DBA_DATA_FILES.BYTES不变,DBA_FREE_SPACE中空闲字节数会增加 - 想真正减小文件体积,必须额外执行:
ALTER DATABASE DATAFILE '/path/to/file.dbf' RESIZE 2G - 但
RESIZE不能小于当前已用上限,否则报ORA-03297;先查最大已用块:SELECT MAX(block_id + blocks - 1) * block_size FROM dba_extents WHERE file_id = N
最容易被忽略的是:shrink 后不 gather stats,BLOCKS 字段仍显示旧值,误判“没生效”;务必跟一句 DBMS_STATS.GATHER_TABLE_STATS。


















