ORA-14006报错主因是源表未通过CAN_REDEF_TABLE检查,常见于含LONG/LOB(未启用ROW MOVEMENT)、函数索引、权限不足、MV LOG未失效或被FOR UPDATE锁定;须先执行CAN_REDEF_TABLE验证。
ORA-14006:执行 DBMS_REDEFINITION.START_REDEFINITION 时报错“invalid partition name”
这通常不是分区名写错了,而是源表压根没被识别为“可重定义对象”——dbms_redefinition.can_redef_table 检查没过。常见原因有三:
- 源表含
LONG、LOB(未启用ENABLE ROW MOVEMENT)、或函数索引(非基于确定性函数) - 用户无
EXECUTE权限给DBMS_REDEFINITION,或对源表/目标表无SELECT+INSERT+ALTER - 表上有未失效的物化视图日志(
MV LOG),或正在被其他会话以FOR UPDATE锁住
先跑一遍 CAN_REDEF_TABLE,别跳过。它不报错,才进下一步。
如何构造正确的中间分区表结构(含 PARTITION BY RANGE 和本地索引)
中间表不是随便建个带分区的表就行——字段顺序、数据类型、NOT NULL 约束、默认值必须和原表完全一致,否则 START_REDEFINITION 会静默失败(日志里只写“redefinition completed”,但数据没同步)。
- 用
DBMS_METADATA.GET_DDL('TABLE', 'TBL_NAME')拿原表 DDL,删掉存储参数、表空间、注释,保留字段定义 - 在末尾加
PARTITION BY RANGE (create_time) (PARTITION p2023 VALUES LESS THAN (TO_DATE('2024-01-01','YYYY-MM-DD')), ...) - 所有索引重建时加
LOCAL;全局索引不能直接搬过来,得等重定义完成后再手工CREATE INDEX ... GLOBAL
特别注意:DATE 分区键要用 TO_DATE 字面量,别用 DATE'2024-01-01'——12c 及以前版本不认这种写法,会报 ORA-14019。
DBMS_REDEFINITION.SYNC_INTERIM_TABLE 调不调?什么时候调?
如果原表写入压力小(QPS FINISH_REDEFINITION 会自动做最后一次同步。但以下情况必须手动 SYNC:
- 原表每秒新增 > 200 行,且重定义过程超过 10 分钟(否则
FINISH阶段锁表时间不可控) - 业务能接受短暂双写(比如凌晨维护窗口),想把锁表时间压到秒级
- 中间表已建好索引、约束,但发现原表有大量未提交事务阻塞了同步
建议策略:先 START → 等中间表数据 copy 完 → 立即 SYNC_INTERIM_TABLE 一次 → 观察 DBA_REDEFINITION_STATUS 中 NUM_ROWS 是否趋近于 0 → 再 FINISH。这样锁表时间基本稳定在 1~3 秒。
重定义后 EXPLAIN PLAN 显示走全表扫描,分区裁剪失效
不是分区没生效,是查询条件没触发裁剪。最常踩的坑是:
- WHERE 条件用了函数包裹分区键,比如
WHERE TO_CHAR(create_time, 'YYYY') = '2023'—— 改成create_time >= DATE'2023-01-01' AND create_time - 绑定变量类型和分区键不匹配(如
create_time是DATE,但传入VARCHAR2绑定变量),导致隐式转换 - 统计信息没更新:
DBMS_STATS.GATHER_TABLE_STATS必须在FINISH_REDEFINITION后立刻执行,且加CASCADE => TRUE
验证是否裁剪:查 PLAN_TABLE 的 OTHER_XML 字段,找 partition_start 和 partition_stop 是否为具体分区号,而不是 KEY 或 ROW LOCATION。
分区重定义真正难的不是语法,是锁表时机和统计信息刷新节奏——差 2 秒没 gather,线上查询就可能降级成全扫。










