dbms_redefinition是在线重定义表结构的机制,仅在alter table shrink space不可用时(如dictionary管理表空间、含basicfile lob、未启用row movement)才作为唯一可行替代方案。

DBMS_REDEFINITION 不是“在线碎片整理工具”,而是在线重定义表结构的机制;它能间接降低高水位线(HWM)和消除段内碎片,但仅在 ALTER TABLE SHRINK SPACE 不可用时才应考虑——比如表空间是 DICTIONARY 管理、含 BASICFILE LOB、或业务不允许锁表且无法启用 ROW MOVEMENT。
为什么 SHRINK SPACE 失效时才轮到 DBMS_REDEFINITION
直接用 ALTER TABLE ... SHRINK SPACE 是最轻量、最可控的碎片处理方式,但它有硬性前提:
- 表空间必须是
LOCAL管理 +AUTOSEGMENT_SPACE_MANAGEMENT = 'AUTO'(即 ASSM) - 必须先执行
ALTER TABLE ... ENABLE ROW MOVEMENT - 对
BASICFILE LOB列完全无效,SHRINK SPACE会跳过该列并报ORA-10637 - 若表空间是
DICTIONARY管理(查DBA_TABLESPACES.EXTENT_MANAGEMENT),SHRINK直接报错,无绕过办法
这些场景下,DBMS_REDEFINITION 才是唯一可行的在线替代方案——它不依赖段管理类型,也不受 LOB 类型限制,本质是重建一张物理紧凑的新表。
执行前必须验证的三件事(缺一不可)
跳过任一检查,大概率卡在 START_REDEF_TABLE 或中途失败:
- 运行
DBMS_REDEFINITION.CAN_REDEF_TABLE('SCHEMA_NAME', 'TABLE_NAME'),确认返回成功;若报ORA-12089(无主键)或ORA-12090(含BFILE、IOT等不支持类型),立即中止 - 查
V$TRANSACTION和V$SESSION,确保源表没有未提交长事务或长时间运行查询,否则SYNC_INTERIM_TABLE会无限等待 - 确认目标表空间空闲块足够:不是看百分比,而是查
DBA_FREE_SPACE中MAX(BYTES)是否 ≥ 预估新表大小;否则SYNC_INTERIM_TABLE报ORA-01653
用 CONS_USE_PK 方式建中间表的关键细节
推荐用主键方式(CONS_USE_PK),比 CONS_USE_ROWID 更稳定、不引入隐藏列 M_ROW$$:
- 中间表只定义列、主键(或伪主键)、必要存储参数(如
PCTFREE 10、SEGMENT CREATION IMMEDIATE),**不要加索引、约束、触发器**——这些由COPY_TABLE_DEPENDENTS统一处理 -
START_REDEF_TABLE必须显式传入options_flag => DBMS_REDEFINITION.CONS_USE_PK,否则默认用ROWID方式 - 如果原表有大量未提交 DML,
SYNC_INTERIM_TABLE可能延迟明显,建议在业务低峰期执行;大表可提前开并行:ALTER SESSION FORCE PARALLEL DML PARALLEL 4
完成重定义后最容易被忽略的两步
FINISH_REDEF_TABLE 成功只代表表名切换完成,旧段释放、性能恢复还差最后两步:
- 索引碎片未处理:
DBMS_REDEFINITION不重建索引,必须手动对每个索引执行ALTER INDEX ... REBUILD ONLINE - 统计信息不会自动刷新:
DBA_TAB_STATISTICS.NUM_ROWS和BLOCKS仍是旧值,优化器估算严重失真;必须立刻执行:DBMS_STATS.GATHER_TABLE_STATS('SCHEMA_NAME', 'TABLE_NAME', CASCADE => TRUE)
这两步不做,SQL 执行计划可能彻底跑偏——你看到的“空间回收了”,很可能只是幻觉。











