Oracle报错:ORA-14402: updating partition key column would cause a partition change
Oracle报错:ORA-14402: updating partition key column would cause a partition change
报错信息
今天在 Oracle 上更新数据的时候,报了如下错误:
ORA-14402: updating partition key column would cause a partition change
意思是:更新分区关键字列将导致分区的更改。
解决办法
然后百度大法,了解到:
1、默认情况下,Oracle 的分区表对于分区字段是不允许进行 update 操作的,如果有对分区字段行进 update,就会报错 ORA-14402。
2、解决办法:开启表的行转移功能
alter table XX enable row movement;--修改语句
alter table XX disable row movement;--修改回来的语句
这样在 update 以后,会在老分区删除数据,新分区插入数据。
3、enable row movement 会改变 rowid。
拓展补充
下面三种情况需要开启 row movement
1、 更新 Partition Key
分区表某一行更新时,如果更新的是分区列,并且更新后的列值不属于原来的这个分区,如果开启了这个选项,就会把这行从这个分区中 delete 掉,并加到更 新后所属的分区。相当于一个隐式的 delete+insert,但是不会触发 insert/delete 触发器。如果没有开启这个选项,就会在更新时报错 ORA-14402;
这一操作产生影响的特殊之处在于这是个 DML 操作,是和 online transaction 密切相关。对于这样一个 UPDATE,实际上分为3步:
先从原有分区将数据删除;将原数据转移到新分区上;更新数据。
其影响就在于以下几个方面:
一 个 UPDATE 被分解为 DELET、INSERT、UPDATE 三个操作,增加了性能负担。其中,DELETE 的查询条件与原 UPDATE 的查询条件相 同,新的 UPDATE 的查询条件是基于 INSERT 生成的新的 ROWID,相应的Redo Log、Undo Log 会增加;
如果 Update 语句还涉及到了 Local Index 的字段的话,新、旧2个分区上的 Local Index 都要被更新。
还有一点,Row Movement 会和域索引(Domain Index)产生冲突:如果表上定义了域索引,开启 Row Movement 就会失败;反之亦然。
2、 Flaskback table to 某时间
Flashback Table 实际是通过Flashback Query将表中数据进行了一次删除、插入操作,因此ROWID会发生变化。
3、 Shrink Segment
Shrink Segment能帮助我们压缩数据段、整理数据碎片、降低高水位,以提高性能、节省空间。
有必要说明一下,row movement 并不是行迁移,最大的区别是行迁移的 rowid 是不变的,行迁移是 update 行记录时,数据块没有足够的空闲容纳数据行,Oracle 将此行移到其他数据块,同时保留此行的rowid不变,并在原数据块建一指针指向新的行位置。这 种情况下,读取一行数据就会访问2个数据块,增加 IO,导致性能下降。
如果直接创建主键,使用的global index,当某分区被 drop 后,主键会失效
ALTER TABLE PHAECDA1.HCPSGLSINFOPZOW_NEW ADD CONSTRAINT PK_STAMP PRIMARY KEY(T_STAMP) tablespace xx;
改为 local index,但不包含分区段,报错:
ALTER TABLE PHAECDA1.HCPSGLSINFOPZOW_NEW ADD CONSTRAINT PK_STAMP PRIMARY KEY(T_STAMP) using index local tablespace xxx;
ORA-14039: partitioning columns must form a subset of key columns of a UNIQUE
ORA-14039: 分区列必须构成 UNIQUE 索引的关键字列子集。
Local index ,主键+分区键 作为新的主键,自动创建分区 index,index 会按分区段 Partition 分区到 table 的分区表空间
ALTER TABLE PHAECDA1.HCPSGLSINFOPZOW_NEW ADD CONSTRAINT PK_STAMP PRIMARY KEY(T_STAMP,CLDATE) USING INDEX LOCAL;
先创建 index,再创建主键,当然,主键也可直接作为分区段。
更多推荐

所有评论(0)