drop tablespace ... including contents and datafiles 不保证磁盘空间立即释放,因oracle进程仍持有已unlink文件的句柄,需用lsof定位并kill对应进程或重启数据库才能真正释放空间。
直接结论:仅执行 drop tablespace ... including contents and datafiles 不保证磁盘空间立即释放,必须确认文件是否真被操作系统 unlink,否则需手动清理残留句柄或重启数据库。
为什么 drop tablespace ... including contents and datafiles 后 df -h 看不到空间回收?
Oracle 在 Linux/Unix 上调用 unlink() 删除数据文件,但若该文件仍被 Oracle 进程(如 DBWn、CKPT)打开持有,内核不会真正释放磁盘块——文件名消失,但 inode 仍被引用,df -h 显示的空间不变。
- 典型现象:
lsof | grep deleted能查到类似/u01/oradata/ORCL/ts_historical01.dbf (deleted)的条目,后面带(deleted)标识 - 根本原因:Oracle 进程未及时关闭对已删文件的 file descriptor 引用,尤其在高负载或 ASSM 表空间下 smon 清理延迟时更常见
- 不是 bug,是 Unix 文件系统语义:只要还有进程 open 着,空间就不可重用
删除前必须做的三件事
跳过任意一步都可能导致失败、锁表、或删错对象:
- 确认无活跃会话连接该表空间:查
v$session和v$transaction,必要时用ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE - 检查是否有对象被 Flashback Data Archive 或 GoldenGate 同步依赖:运行
SELECT * FROM dba_flashback_archive_tables WHERE tablespace_name = 'TS_HISTORICAL';查dba_gg_sessions(若启用 GG) - 验证表空间是否为默认临时表空间或默认表空间:查
database_properties中DEFAULT_TEMP_TABLESPACE和DEFAULT_PERMANENT_TABLESPACE,避免误删系统关键表空间
删除后空间未释放的两种可靠处理方式
优先选方式一(轻量),方式二(彻底但有停机):
- 方式一:定位并 kill 持有句柄的进程
执行lsof | grep 'ts_historical.*deleted',找出 PID;
用kill -9 <pid></pid>干掉对应进程(通常是 DBW0、DBW1 等后台写进程);
再等 10–30 秒,df -h通常立即更新 - 方式二:重启数据库实例
SHUTDOWN IMMEDIATE会强制关闭所有文件句柄;STARTUP后,内核真正回收空间;
注意:此操作影响所有业务,且需确保控制文件、联机日志路径有效,避免启动失败
resize datafile 不能替代表空间删除
有人试图绕过 drop tablespace,改用 ALTER DATABASE DATAFILE 'xxx.dbf' RESIZE 缩小单个文件——这在表空间含多个数据文件或存在跨文件段时无效,且容易触发 ORA-03297(请求 resize 值小于实际使用上限)。
-
RESIZE只能缩小到当前最高已分配 block 所在位置,无法跨文件腾挪;而drop tablespace ... and datafiles是唯一能整块移除物理文件的操作 - 若误删了数据文件但数据库仍在运行,别硬重启:先用
ALTER DATABASE DATAFILE '<path>' OFFLINE DROP</path>标记为离线再处理,否则SHUTDOWN IMMEDIATE会报ORA-01116
最易被忽略的点:Oracle 19c 默认启用回收站(RECYCLEBIN=ON),即使加了 INCLUDING CONTENTS,若表空间内对象曾被 DROP 过未 PURGE,元数据残留可能干扰清理。建议删除前先清空:PURGE DBA_RECYCLEBIN(需 SYSDBA 权限)。











