DELETE 不会降低高水位线(HWM),故 BLOCKS 字段不变、表空间物理尺寸不变;TRUNCATE 可重置 HWM 但不可回滚且受外键等限制;SHRINK SPACE 需先启用行移动、分阶段锁表,最后须手动 RESIZE 数据文件才能释放磁盘空间。

DELETE 不会降低高水位线(HWM),所以表空间物理尺寸不变,这是 Oracle 的正常行为,不是 bug。
为什么 DELETE 后 blocks 字段不降
Oracle 表的存储以“段(segment)”为单位管理,HWM 是段内已分配块与未分配块的分界线。INSERT 会推高 HWM,但 DELETE 只标记行为空闲,不回收块、不移动 HWM。全表扫描仍需遍历到原 HWM 位置,BLOCKS 字段值保持不变。
-
NUM_ROWS变小,但BLOCKS仍很大 → 典型 HWM 虚高现象 - 查真实占用:先执行
DBMS_STATS.GATHER_TABLE_STATS('SCHEMA', 'TABLE_NAME'),再查SELECT blocks, num_rows FROM user_tables WHERE table_name = 'YOUR_TABLE' - 操作系统级磁盘空间(.dbf 文件大小)完全不受 DELETE 影响
TRUNCATE 能重置 HWM,但有硬限制
TRUNCATE TABLE your_table DROP STORAGE 会清空数据、归零 HWM、释放段内空间,但必须满足:
- 事务不可回滚,执行即生效
- 表不能被任何外键引用(否则报
ORA-02266) - 不能启用 Flashback Data Archive
- 即使成功,
.dbf文件本身仍不会缩小 —— 这步常被忽略
SHRINK SPACE 需开行移动,且分阶段锁表
在线业务场景下唯一可行的收缩方式,但操作链不能省略:
- 先启用行迁移:
ALTER TABLE your_table ENABLE ROW MOVEMENT -
SHRINK SPACE COMPACT:只整理碎片,期间加 RX 锁,允许 DML -
SHRINK SPACE或SHRINK SPACE CASCADE:真正下调 HWM,第二阶段需短暂 X 锁,所有 DML 阻塞 - 收缩后务必关闭行移动:
ALTER TABLE your_table DISABLE ROW MOVEMENT,否则影响依赖ROWID的逻辑
数据文件不 resize,磁盘空间就永远不回来
HWM 降了,只是段内空间回收;操作系统看不到变化,因为数据文件物理尺寸没变。必须手动收缩文件:
- 确认末尾有足够连续空闲:
SELECT file_name, bytes/1024/1024 AS curr_mb, (bytes - NVL((SELECT SUM(bytes) FROM dba_free_space WHERE file_id = d.file_id), 0))/1024/1024 AS used_mb FROM dba_data_files d WHERE tablespace_name = 'YOUR_TS' - 只在
curr_mb - used_mb > 100(MB)时才值得 resize - 执行:
ALTER DATABASE DATAFILE '/path/to/file.dbf' RESIZE 5000M
很多人做完 SHRINK 就以为完事了,其实最后这一步才是让磁盘空间真正“松口气”的关键动作。


















