ALTER TABLESPACE COALESCE 对本地管理表空间无效,仅适用于已淘汰的字典管理表空间;缓解碎片需收缩段(如 SHRINK SPACE CASCADE),而非合并表空间。
alter tablespace coalesce 对绝大多数 oracle 表空间无效,它只对字典管理表空间(dictionary)中的自由空间起作用,而这类表空间在 10g 及以后版本已基本淘汰;当前主流的本地管理表空间(local)执行该命令会静默失败或直接报错 ora-1145(除非表空间处于只读状态且恰好满足极苛刻条件)。
COALESCE 在本地管理表空间中根本不起作用
本地管理表空间使用位图跟踪空闲空间,不依赖数据字典中的 free space 记录。ALTER TABLESPACE ... COALESCE 的设计初衷是合并字典管理表空间中相邻但未登记为“连续”的自由范围(extents),而本地管理表空间的位图本身已隐含连续性判断逻辑——它不存储“碎片化”的自由块概念,只记录哪些 extent 可用。所以:
- 执行
ALTER TABLESPACE tbs_name COALESCE后查dba_free_space,行数、块数、最大空闲块尺寸几乎不会变化 - 即使表空间里全是小于 64KB 的碎块,
COALESCE也不会把它们拼成一个大块 - 该命令在 12c/19c/21c 中对
EXTENT MANAGEMENT LOCAL表空间返回ORA-1145: database must be open for COALESCE或直接无响应
真正能缓解碎片的操作是收缩段,不是合并表空间
表空间“看起来满”但实际无法分配新 extent,根源不在表空间层面,而在其内部段(表、索引)的高水位线(HWM)卡住、空闲块散落、且未被重用。必须逐个处理段:
-
SHRINK SPACE CASCADE是首选:适用于 ASSM 表空间中的普通表,需先ENABLE ROW MOVEMENT,会下调 HWM 并重建索引 - 含
SECUREFILE LOB的表,SHRINK SPACE CASCADE会跳过 LOB 段,得单独跑ALTER TABLE t MODIFY LOB (col) (SHRINK SPACE) - 非 ASSM 表空间或含
BASICFILE LOB的表,只能用ALTER TABLE t MOVE+ALTER INDEX i REBUILD,且 MOVE 前要确认目标表空间有足够连续空间 - 收缩后必须手动执行
DBMS_STATS.GATHER_TABLE_STATS,否则优化器仍按旧BLOCKS值估算,可能选错执行计划
误用 COALESCE 会掩盖真实问题
有人看到 dba_free_space 里碎片行数多,就反复执行 COALESCE 并观察是否变少——这完全是徒劳。更危险的是,这种操作会让人误以为“已经处理过了”,从而跳过真正有效的诊断步骤:
- 没查
dba_segments和dba_extents确认哪些表的HWM偏高 - 没用
DBMS_SPACE.SPACE_USAGE看单个表的实际空闲块分布(比如fs1_blocks占比是否异常高) - 没核对
SELECT extent_management FROM dba_tablespaces,盲目对LOCAL表空间执行字典管理命令 - 在业务高峰期跑
SHRINK SPACE CASCADE,因短暂 X 锁导致应用超时,却归咎于“COALESCE 没用”
碎片不是靠一条表空间级命令能“一键清理”的东西;它反映的是长期 DML 模式与空间管理策略的不匹配。最常被忽略的点是:收缩完所有可处理的表之后,如果表空间内仍有大量不可收缩的对象(如物化视图日志、审计表、历史分区),那唯一彻底办法就是 expdp + 新建表空间 + impdp —— 而不是继续折腾 COALESCE。











