赞
踩
正如大家所知道的,OceanBase兼容Oracle的rowid特性,但在其生成规则上却存在不同,具体表现如下:
● 定义:OceanBase(简称 OB)的rowid是通过主键(包括隐藏主键)直接经过base64编码计算得出的,因此一旦主键发生变动,相应的rowid也会随之改变。关于主键的生成规则,具体如下:
○有主键非分区表,用户定义的主键
○有主键分区表,用户定义的主键
○无主键非分区表,内部生成sequence作为隐藏主键
○无主键分区表,分区键+sequence作为隐藏主键
●长度:17个字符。
●定义:该值表明了该行在oracle数据库中的物理具体位置。保存rowid需要10个字节或者是80个位二进制位。这80个二进制位分别是:
○1. 数据对象编号,表明此行所属的数据库对象的编号,每个数据对象在数据库建立的时候都被唯一分配一个编号,并且此编号唯一。数据对象编号占用大约32位。
○2. 对应文件编号,表明该行所在文件的编号,表空间的每一个文件标号都是唯一的。文件编号所占用的位置是10位。
○3. 块编号,表明改行所在文件的块的位置块编号需要22位。
○4. 行编号,表明该行在行目录中的具体位置行编号需要16位。
●长度:rowid需要 10个字节的存储空间,并用18个字符来显示。
●表A:存储业务单据信息,数据量较大;
●表B:A表关联表,表中有一列存放B表的rowid值;
●业务场景需要经常通过B表去A表关联取数,为了优化取数性能直接通过rowid关联。
由于迁移后OB rowid长度和Oracle不一致,且定义完全不同,列数据迁移过去会失去原有意义成为垃圾数据。具体改造方案如下:
1.表结构调整:删除rowid类型列,数据也不做迁移;
2.性能调优:创建合适索引,通过其他字段关联查询。由于业务侧预留了业务主键可以关联,实测性能满足客户需求。
由于OMS迁移过程中全量和增量迁移都和源端oracle的rowid密切关联(无论有主键表还是无主键表),所以我们需要密切关注Oracle源端的rowid变化场景,迁移过程中都要避免。Oracle rowid发生变化的场景如下:
○1. Oracle 行迁移
○2. 另外一些不急于rowmovement会导致rowid修改的动作,比如move和逻辑导出再导入
●行迁移 ( Row movement): 默认情况下,oracle数据块中的一行其生命周期内是不会发生移动的,即块的rowid不会发生改变。但是在某些情景下,我们希望行的rowid可以发生变化,这时候我们就需要启动表的row movement特性。
- -- 启用row movement特性
- Alter table table_name enable row movement;
当我们允许分区表的分区键是可更新的时候,如果分区键的更新导致当前修改的数据条目需要移动到其他分区,此时就会发生rowid的改变。
- create table test_rowid(id number,test_value varchar2(10))
- partition by list(test_value)(
- partition p1 values('1'),
- partition p2 values('2'),
- partition p3 values('3'));
-
- insert into test_rowid values(1,'1');
- insert into test_rowid values(2,'2');
- insert into test_rowid values(3,'3');
- insert into test_rowid values(4,'1');
- commit;
-
- select rowid,id,test_value from test_rowid ;
- /*ROWID ID TEST_VALUE
- AAAefAAAHAADJMWAAA 1 1
- AAAefAAAHAADJMWAAB 4 1
- AAAefBAAHAADJcWAAA 2 2
- AAAefCAAHAADJsWAAA 3 3 */
-
- update test_rowid set test_value=2 where id=4;
- -- ORA-14402: updating partition key column would cause a partition change
-
- alter table test_rowid enable row movement;
-
- update test_rowid set test_value=2 where id=4;
- -- 1 row updated.
-
- select rowid,id,test_value from test_rowid ;
- /*ROWID ID TEST_VALUE
- AAAefAAAHAADJMWAAA 1 1
- AAAefBAAHAADJcWAAA 2 2
- AAAefBAAHAADJcWAAB 4 2
- AAAefCAAHAADJsWAAA 3 3 */
- id=4的列rowid发生变化。
在闪回操作时,我们同样需要开启表的row movement特性。
- alter table test_rowid disable row movement;
- -- Table altered.
-
- SQL> select current_scn from v$database;
- -- 38719199
-
- select rowid,id,test_value from test_rowid where test_value=1;
- /* ROWID ID TEST_VALUE
- AAAefAAAHAADJMWAAA 1 1 */
-
- delete from test_rowid where test_value=1;
- commit;
-
- flashback table test_rowid to scn 38719199;
- -- ORA-08189: cannot flashback the table because row movement is not enabled
-
- alter table test_rowid enable row movement;
- -- Table altered.
-
- flashback table test_rowid to scn 38719199;
- -- Flashback complete.
-
- select rowid,id,test_value from test_rowid where test_value=1;
- /* ROWID ID TEST_VALUE
- AAAefAAAHAADJMWAAC 1 1 */
flashback table原理:oracle flashback table 是通过临时表来实现的。
- create table hh(id number);
- insert into hh values(1);
- commit;
-
- alter table hh enable row movement;
- select current_scn from v$database;
- -- 1635103
-
- update hh set id = 2;
- commit;
-
- alter session set tracefile_identifier = 'ee';
- alter session set sql_trace=true;
- flashback table hh to scn 1635103;
- -- Flashback complete.
-
-
- 通过查看trace文件,我们可以发现oracle flashback table 是通过一个临时表sys_temp_fbt来实现的。
- trace文件中的部分内容如下:
- ********************************************************************************
- sqlid='dtjmzuugu6ktw'
- INSERT /*+ APPEND */ into SYS_TEMP_FBT SELECT /*+ FBTSCAN FULL(S) PARALLEL(S, DEFAULT) */ :1, :2, :3, rowid, SYS_FBT_INSDEL FROM "APPTEST"."HH" as of SCN :4 S
- ********************************************************************************
- sqlid='bytpvbcb8zbb6'
- /* Flashback Table */ DELETE /*+ BYPASS_UJVC */ FROM (SELECT /*+ ORDERED USE_NL(S) PARALLEL(S,DEFAULT) PARALLEL(T,DEFAULT) */ S.rowid FROM SYS_TEMP_FBT T, "APPTEST"."HH" S WHERE T.rid = S.rowid and T.action = 'D' and T.object# = : 1) V
- ********************************************************************************
- sqlid='a3h5cbfc5b6xv'
- /* Flashback Table */ INSERT /*+ PARALLEL(S, DEFAULT) PARALLEL(T, DEFAULT) */ INTO "APPTEST"."HH" SELECT /*+ USE_NL(S) ORDERED PARALLEL(S, DEFAULT) PARALLEL(T, DEFAULT) */ S.* FROM SYS_TEMP_FBT T , "APPTEST"."HH" as of SCN :1 S WHERE T.rid = S.rowid and T.action = 'I' and T.object# = :2
-
- 由此可见,oracle是通过SYS_TEMP_FBT进行删除操作,而后进行插入操作,
- 因此行的rowid有可能发生改变。
- SQL> select * from sys_temp_fbt ;
- SCHEMA OBJECT_NAME OBJECT# RID A
- ---------- -------------------- ---------- ------------------------------ -
- hh hh 76906 AAASxqAAGAAAAC0AAA D
- hh hh 76906 AAASxqAAGAAAAC0AAA I
-
-
- SQL> select tname,tabtype from tab;
- TNAME TABTYPE
- ------------------------------ -------
- HH TABLE
- SYS_TEMP_FBT TABLE
drop表Oracle有另外的回收站技术恢复,不需要开ROW MOVEMENT
- SQL> ALTER TABLE test_rowid DISABLE ROW MOVEMENT;
- Table altered.
- SQL> DROP TABLE test_rowid;
- Table dropped.
- SQL> FLASHBACK TABLE test_rowid TO BEFORE DROP;
- Flashback complete.
- 没错,因为drop表Oracle有另外的回收站技术恢复过来,而删除几行记录是不能 直接通过回收站恢复的。
在收缩空间时,也会造成行的移动
- SQL> alter table hh disable row movement;
- Table altered.
-
- SQL> alter table hh shrink space;
- alter table hh shrink space
- *
- ERROR at line 1:
- ORA-10636: ROW MOVEMENT is not enabled
-
- SQL> alter table hh enable row movement;
- Table altered.
-
- SQL> alter table hh shrink space;
- Table altered.
-
- Shrink space操作(without compact)也会导致所有已经打开的游标失效,因此需要谨慎使用!
对于源端是OB的情况,OMS迁移并不会依赖rowid,通过前面的介绍也可以看到OB rowid的变化是很频繁的,主要变化场景如下:
●有主键非分区表,主键发生变化,rowid变化
●有主键分区表,因为分区键包含在主键内,所以同上
●无主键非分区表,对于一行记录rowid不会变化。
●无主键分区表,分区键发生变化时,rowid变化
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。