Hash分区表在线重定义必须满足:源表有主键;操作用户具EXECUTE_CATALOG_ROLE及CREATE/ALTER/SELECT ANY TABLE权限;中间表与源表同schema;表空间剩余容量≥源表2倍;不在SYS/SYSTEM下操作。
Hash分区表在线重定义必须满足的硬性条件
不满足以下任意一条,dbms_redefinition.can_redef_table 就会直接报错,后续步骤无法执行:
- 源表必须有主键(
ORA-12089是最常见拦截项) - 操作用户需具备
EXECUTE_CATALOG_ROLE权限,且被授予CREATE ANY TABLE、ALTER ANY TABLE、SELECT ANY TABLE等权限 - 中间表(interim table)与源表必须在**同一 schema 下**,不能跨用户
- 表空间剩余容量至少为源表当前大小的 2 倍(重定义过程会同时存在原表 + 中间表)
- 不能在
SYS或SYSTEM用户下操作
创建中间表时 Hash 分区的关键写法
中间表结构必须与源表字段完全一致(含类型、长度、NULL 属性),但需显式声明 Hash 分区。容易出错的是分区列选择和分区数设定:
- 分区列必须是源表中已存在的列,且最好是非空、高基数列(如
ID、ORDER_ID),避免数据倾斜 - 分区数量建议为 2 的幂次(如 4、8、16),Oracle 内部哈希算法对这类值更友好
-
PARTITION BY HASH后不能带STORE IN子句;每个PARTITION必须显式指定TABLESPACE - 示例:
CREATE TABLE t_hash_interim (ID NUMBER PRIMARY KEY, NAME VARCHAR2(32)) PARTITION BY HASH(ID) (PARTITION p1 TABLESPACE users, PARTITION p2 TABLESPACE users, PARTITION p3 TABLESPACE users, PARTITION p4 TABLESPACE users);
执行重定义三步不可跳过
顺序错误或遗漏会导致中间表数据不一致、依赖对象丢失,甚至锁表时间延长:
- 先调用
DBMS_REDEFINITION.START_REDEF_TABLE启动重定义,此时开始全量复制 - 再执行
DBMS_REDEFINITION.SYNC_INTERIM_TABLE多次(尤其在长事务期间),确保增量变更同步到位;该步骤可反复运行,无副作用 - 最后调用
DBMS_REDEFINITION.FINISH_REDEF_TABLE—— 这是原子交换,耗时极短(通常几秒),但要求源表无未提交 DDL(如正在建索引)
注意:FINISH_REDEF_TABLE 不会自动迁移索引/约束/触发器;必须额外调用 DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS,且参数 copy_indexes 设为 1 才能复制索引。
重定义后 Hash 分区表的行迁移问题
Hash 分区表默认禁止更新分区键(ORA-14402),但业务常需修改如 ID 字段。解决方法不是禁用行迁移,而是提前启用:
- 在
FINISH_REDEF_TABLE成功后立即执行:ALTER TABLE t_hash ENABLE ROW MOVEMENT; - 否则后续
UPDATE分区键会失败;启用后 Oracle 允许行在分区间物理移动,代价是增加 I/O 和可能的锁等待 - 检查是否生效:
SELECT table_name, row_movement FROM user_tables WHERE table_name = 'T_HASH';返回ENABLED即可
真正麻烦的是分区键变更后的性能隐忧:一次 UPDATE 可能触发跨分区移动 + 索引维护 + 触发器重执行,务必在业务低峰期验证实际负载。











