不能直接 shrink space 一个带 LOB 的分区表——它会静默跳过 LOB 段,空间几乎不释放;真正有效的收缩必须分三步:先 move 分区(含 LOB),再 shrink 表或索引,最后 resize 数据文件。
不能直接 shrink space 一个带 lob 的分区表——它会静默跳过 lob 段,空间几乎不释放。 真正有效的收缩必须分三步:先 move 分区(含 lob),再 shrink 表或索引,最后 resize 数据文件。漏掉任何一步,操作系统级空间就收不回来。
为什么 shrink space 对带 LOB 的分区表基本无效
Oracle 的 shrink space 命令默认只作用于堆表段(heap segment),对 LOBSEGMENT 和 LOBINDEX 完全无感知。即使你对分区表执行了 alter table t move partition p2023 shrink space compact,LOB 字段仍留在原表空间、原数据块里,高水位线(HWM)也不动。查 dba_segments 会发现 LOB 段大小纹丝不动,dba_free_space 也没变化。
- 常见错误现象:
shrink space compact执行成功但bytes不降,误以为命令生效 - 根本原因:LOB 是独立段(
segment_type = 'LOBSEGMENT'),需单独处理 - 分区表下 LOB 还分两种:全局 LOB(所有分区共用一个 LOB 段)和局部 LOB(每个分区对应独立 LOB 段),后者更常见也更难批量处理
分区表 + LOB 字段的正确收缩顺序
必须按「move → shrink → resize」严格顺序操作,且每步都要确认对象状态。中间任意一步失败,后续操作可能报错或无效。
- 第一步:move 分区并指定新 LOB 表空间
例如迁移分区p2023及其 CLOB 字段CONTENT到LOB_DATA表空间:alter table LOG_RECORDS move partition p2023 lob(CONTENT) store as (tablespace LOB_DATA); - 第二步:重建该分区上的本地索引(如果存在)
alter index IDX_LOG_TIME rebuild partition p2023; - 第三步:对表本身执行
shrink space cascade(仅对堆段有效,但能顺带 shrink 本地索引段)alter table LOG_RECORDS shrink space cascade; - 第四步:单独 shrink LOB 段(关键!否则空间不释放)
alter table LOG_RECORDS modify lob(CONTENT) (shrink space);
LOB 段 shrink 后仍无法 resize 数据文件?检查 HWM 位置
执行完 modify lob(...) shrink space 后,LOB 段的 HWM 会下移,但数据文件本身的 HWM 不会自动更新。必须手动查出可安全收缩的上限值,再执行 resize。
- 查当前数据文件 HWM(单位 MB):
select file_id, round(max(block_id)*8/1024) hwmsize_mb from dba_extents where file_id = &file_id group by file_id; - 查该文件已分配总大小:
select file_name, round(bytes/1024/1024) total_mb from dba_data_files where file_id = &file_id; - 真正能
resize的最小值必须 ≥hwmsize_mb,否则报 ORA-03297 - 典型误操作:直接
resize 100M,而实际 HWM 在 215M,结果命令失败且锁住文件
LONG 类型字段怎么办?别碰 move 或 shrink
Oracle 明确禁止对含 LONG 列的表执行 move、shrink、enable row movement。一旦表里有 LONG,唯一可靠路径是逻辑导出导入。
- 必须用
expdp/impdp,配合REMAP_TABLESPACEexpdp user/pwd directory=EXP_DIR tables=T_WITH_LONG dumpfile=t_long.dmpimpdp user/pwd directory=EXP_DIR dumpfile=t_long.dmp remap_tablespace=USERS:NEW_TS - 注意:IMPDP 时若目标表空间已存在同名表,需加
table_exists_action=replace - 这个过程会重建整个段结构,LOB 和 LONG 都一并处理,但停机时间长,务必在维护窗口内操作
最易被忽略的一点:modify lob(...) shrink space 虽然能释放表空间内碎片,但它不会把空间还给操作系统——只有后续 alter database datafile ... resize 才能做到。很多人卡在这一步,以为 shrink 完就结束了,其实离磁盘空间真正回收还差最后一跳。


















