DELETE后表空间使用率未降是因为HWM未降低,DELETE仅标记行删除而不回收块、不释放extent,已分配空间仍被表段持有;需用TRUNCATE重置HWM或SHRINK SPACE(先启ROW MOVEMENT)配合RESIZE才能真正释放空间。
DELETE后表空间使用率没降,是因为HWM卡住了
oracle的delete只标记数据块为空闲,不移动高水位线(hwm),也不释放区(extent)——这些已分配的空间仍被表段持有,dba_segments.bytes不会变,表空间使用率自然“虚高”。这不是bug,是设计使然:hwm保障后续insert能快速复用块,但代价是空间不自动返还。
验证是否真被HWM卡住,跑这条SQL:SELECT segment_name, bytes/1024/1024 AS mb, blocks FROM dba_segments WHERE segment_name = 'YOUR_TABLE' AND owner = 'YOUR_SCHEMA';
再对比实际数据量:SELECT COUNT(*) FROM your_table;。如果MB远大于预期(比如几万行占几个GB),基本就是HWM问题。
TRUNCATE能彻底重置HWM,但不可回滚
如果目标是清空整张表或保留极少数据(比如只留最近7天),TRUNCATE TABLE your_table DROP STORAGE;是最干脆的解法。它直接释放全部区、重置HWM、不走UNDO、不触发触发器,执行快且空间立刻回收。
注意两个硬约束:
• 必须有DROP ANY TABLE或表级ALTER权限
• 不能在有外键引用的表上直接执行(会报ORA-02266),得先禁用约束或改用TRUNCATE ... CASCADE(12c+支持)
• 执行后无法通过ROLLBACK恢复——别在生产环境手抖运行
SHRINK SPACE适合在线收缩,但要开ROW MOVEMENT
如果必须保留大部分数据、且业务不能停,用SHRINK。但它不是“一键压缩”,得按顺序做三步:
- 先启用行迁移:
ALTER TABLE your_table ENABLE ROW MOVEMENT; - 再执行收缩(推荐带
COMPACT先试):ALTER TABLE your_table SHRINK SPACE COMPACT;(允许并发DML,但HWM不降) - 最后真正下移HWM:
ALTER TABLE your_table SHRINK SPACE;(会短暂阻塞DML)
常见坑:
• 忘开ROW MOVEMENT直接shrink → 报ORA-10636
• 没加CASCADE导致索引没收缩 → SHRINK SPACE CASCADE才同步处理索引段
• 表上有基于函数的索引或域索引 → SHRINK不支持,会报ORA-10631
别忘了Undo表空间可能也在撑爆磁盘
大批量DELETE会疯狂写Undo,尤其未分批提交时。即使表空间看着没涨,UNDOTBS1可能已占满——查它:SELECT tablespace_name, ROUND(used_space*8/1024/1024,2) used_gb FROM v$undostat WHERE begin_time = (SELECT MAX(begin_time) FROM v$undostat);
如果确认是Undo撑爆,优先查长事务:SELECT sid, serial#, start_time, used_ublk FROM v$transaction ORDER BY used_ublk DESC;
杀掉异常会话比换Undo表空间更安全。真要切换,务必按顺序:CREATE UNDO TABLESPACE → ALTER SYSTEM SET undo_tablespace= → DROP TABLESPACE ... INCLUDING CONTENTS AND DATAFILES。删完还得手动rm物理文件,否则磁盘空间不释放。


















