DELETE不降低HWM,导致空间虚高;确认方法是查user_tables中blocks远大于num_rows;TRUNCATE可重置HWM但不可回滚且有外键等限制;SHRINK需先启用行移动并注意锁;最后须RESIZE数据文件才能释放磁盘空间。

DELETE 不会降低高水位线(HWM),所以表空间使用率看起来“卡住”了——这不是故障,是 Oracle 的存储设计逻辑。
怎么确认是 HWM 导致的虚高占用?
别只看 DBA_SEGMENTS.BYTES 或表空间剩余率。真实水位得查块级统计:
- 先收集准确统计:
EXEC DBMS_STATS.GATHER_TABLE_STATS('YOUR_SCHEMA', 'YOUR_TABLE') - 再查关键字段:
SELECT blocks, empty_blocks, num_rows FROM user_tables WHERE table_name = 'YOUR_TABLE'
blocks 是当前 HWM 对应的总块数;empty_blocks 是 HWM 下明确为空的块;如果 num_rows 很小但 blocks 仍高达几万,基本可以断定 HWM 虚高。
TRUNCATE 能重置 HWM,但真能用吗?
TRUNCATE TABLE your_table DROP STORAGE 是最干脆的解法:HWM 归零、段收缩、空间立即释放。但它有硬约束:
- 不可回滚,事务一提交就生效
- 表不能被任何外键引用,否则报
ORA-02266 - 若有 Flashback Data Archive 启用,直接报错
- 即使成功,数据文件(.dbf)物理尺寸不会变——还得手动
ALTER DATABASE DATAFILE ... RESIZE
在线收缩 SHRINK SPACE 要开行移动,也得锁表
业务不能停?那就走 SHRINK SPACE,但它不是无感操作:
- 必须先启用:
ALTER TABLE your_table ENABLE ROW MOVEMENT(否则报ORA-10636) -
SHRINK SPACE COMPACT只整理碎片、不降 HWM,期间加 RX 锁,影响小 -
SHRINK SPACE才真正移动 HWM,第二阶段需短暂 X 锁,所有 DML 阻塞 - 带
CASCADE参数可连索引一起收缩,避免后续手动REBUILD - 执行完记得
DISABLE ROW MOVEMENT,否则可能干扰依赖rowid的逻辑
收缩完了,磁盘空间还是没回来?
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)以上,才值得收缩文件 - 执行:
ALTER DATABASE DATAFILE 'your_file.dbf' RESIZE xxxM
注意:如果 RESIZE 报 ORA-03297,说明目标尺寸太小,得调大一点——HWM 和文件末尾空闲区未必完全对齐。


















