OceanBase 中的ROWID与Oracle的差异与如何迁移

2024-05-07 14:04

本文主要是介绍OceanBase 中的ROWID与Oracle的差异与如何迁移,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. ROWID

1.1 OB和Oracle中rowid的区别

正如大家所知道的,OceanBase兼容Oracle的rowid特性,但在其生成规则上却存在不同,具体表现如下:

OceanBase

● 定义:OceanBase(简称 OB)的rowid是通过主键(包括隐藏主键)直接经过base64编码计算得出的,因此一旦主键发生变动,相应的rowid也会随之改变。关于主键的生成规则,具体如下:

   ○有主键非分区表,用户定义的主键

   ○有主键分区表,用户定义的主键

   ○无主键非分区表,内部生成sequence作为隐藏主键

   ○无主键分区表,分区键+sequence作为隐藏主键

●长度:17个字符。

Oracle

●定义:该值表明了该行在oracle数据库中的物理具体位置。保存rowid需要10个字节或者是80个位二进制位。这80个二进制位分别是:

   ○1. 数据对象编号,表明此行所属的数据库对象的编号,每个数据对象在数据库建立的时候都被唯一分配一个编号,并且此编号唯一。数据对象编号占用大约32位。

   ○2. 对应文件编号,表明该行所在文件的编号,表空间的每一个文件标号都是唯一的。文件编号所占用的位置是10位。

   ○3. 块编号,表明改行所在文件的块的位置块编号需要22位。

   ○4. 行编号,表明该行在行目录中的具体位置行编号需要16位。

●长度:rowid需要 10个字节的存储空间,并用18个字符来显示。

1.2 用户业务场景和迁移方案

业务场景

●表A:存储业务单据信息,数据量较大;

●表B:A表关联表,表中有一列存放B表的rowid值;

●业务场景需要经常通过B表去A表关联取数,为了优化取数性能直接通过rowid关联。

迁移方案

由于迁移后OB rowid长度和Oracle不一致,且定义完全不同,列数据迁移过去会失去原有意义成为垃圾数据。具体改造方案如下:

  1.表结构调整:删除rowid类型列,数据也不做迁移;

  2.性能调优:创建合适索引,通过其他字段关联查询。由于业务侧预留了业务主键可以关联,实测性能满足客户需求。

1.3 Oracle rowid发生变化的场景

由于OMS迁移过程中全量和增量迁移都和源端oracle的rowid密切关联(无论有主键表还是无主键表),所以我们需要密切关注Oracle源端的rowid变化场景,迁移过程中都要避免。Oracle rowid发生变化的场景如下:

○1. Oracle 行迁移

○2. 另外一些不急于rowmovement会导致rowid修改的动作,比如move和逻辑导出再导入

Oracle 行迁移(row movement)场景

●行迁移 ( Row movement): 默认情况下,oracle数据块中的一行其生命周期内是不会发生移动的,即块的rowid不会发生改变。但是在某些情景下,我们希望行的rowid可以发生变化,这时候我们就需要启动表的row movement特性。

-- 启用row movement特性
Alter table table_name enable row movement;
(1)分区表

当我们允许分区表的分区键是可更新的时候,如果分区键的更新导致当前修改的数据条目需要移动到其他分区,此时就会发生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 changealter 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发生变化。
(2)闪回操作

在闪回操作时,我们同样需要开启表的row movement特性。

alter table test_rowid disable row movement;
-- Table altered.SQL> select current_scn from v$database;
-- 38719199select 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 enabledalter 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;
--  1635103update 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             ISQL> 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有另外的回收站技术恢复过来,而删除几行记录是不能 直接通过回收站恢复的。
(3)回收空间

在收缩空间时,也会造成行的移动

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 enabledSQL> alter table hh enable row movement;
Table altered.SQL> alter table hh shrink space;
Table altered.Shrink space操作(without  compact)也会导致所有已经打开的游标失效,因此需要谨慎使用!

1.4 OB rowid变化场景:

对于源端是OB的情况,OMS迁移并不会依赖rowid,通过前面的介绍也可以看到OB rowid的变化是很频繁的,主要变化场景如下:

●有主键非分区表,主键发生变化,rowid变化

●有主键分区表,因为分区键包含在主键内,所以同上

●无主键非分区表,对于一行记录rowid不会变化。

●无主键分区表,分区键发生变化时,rowid变化

这篇关于OceanBase 中的ROWID与Oracle的差异与如何迁移的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/967559

相关文章

Oracle查询表结构建表语句索引等方式

《Oracle查询表结构建表语句索引等方式》使用USER_TAB_COLUMNS查询表结构可避免系统隐藏字段(如LISTUSER的CLOB与VARCHAR2同名字段),这些字段可能为dbms_lob.... 目录oracle查询表结构建表语句索引1.用“USER_TAB_COLUMNS”查询表结构2.用“a

Oracle数据库定时备份脚本方式(Linux)

《Oracle数据库定时备份脚本方式(Linux)》文章介绍Oracle数据库自动备份方案,包含主机备份传输与备机解压导入流程,强调需提前全量删除原库数据避免报错,并需配置无密传输、定时任务及验证脚本... 目录说明主机脚本备机上自动导库脚本整个自动备份oracle数据库的过程(建议全程用root用户)总结

MySQL 迁移至 Doris 最佳实践方案(最新整理)

《MySQL迁移至Doris最佳实践方案(最新整理)》本文将深入剖析三种经过实践验证的MySQL迁移至Doris的最佳方案,涵盖全量迁移、增量同步、混合迁移以及基于CDC(ChangeData... 目录一、China编程JDBC Catalog 联邦查询方案(适合跨库实时查询)1. 方案概述2. 环境要求3.

C# 比较两个list 之间元素差异的常用方法

《C#比较两个list之间元素差异的常用方法》:本文主要介绍C#比较两个list之间元素差异,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. 使用Except方法2. 使用Except的逆操作3. 使用LINQ的Join,GroupJoin

mysql查询使用_rowid虚拟列的示例

《mysql查询使用_rowid虚拟列的示例》MySQL中,_rowid是InnoDB虚拟列,用于无主键表的行ID查询,若存在主键或唯一列,则指向其,否则使用隐藏ID(不稳定),推荐使用ROW_NUM... 目录1. 基本查询(适用于没有主键的表)2. 检查表是否支持 _rowid3. 注意事项4. 最佳实

Oracle 数据库数据操作如何精通 INSERT, UPDATE, DELETE

《Oracle数据库数据操作如何精通INSERT,UPDATE,DELETE》在Oracle数据库中,对表内数据进行增加、修改和删除操作是通过数据操作语言来完成的,下面给大家介绍Oracle数... 目录思维导图一、插入数据 (INSERT)1.1 插入单行数据,指定所有列的值语法:1.2 插入单行数据,指

Conda虚拟环境的复制和迁移的四种方法实现

《Conda虚拟环境的复制和迁移的四种方法实现》本文主要介绍了Conda虚拟环境的复制和迁移的四种方法实现,包括requirements.txt,environment.yml,conda-pack,... 目录在本机复制Conda虚拟环境相同操作系统之间复制环境方法一:requirements.txt方法

Oracle修改端口号之后无法启动的解决方案

《Oracle修改端口号之后无法启动的解决方案》Oracle数据库更改端口后出现监听器无法启动的问题确实较为常见,但并非必然发生,这一问题通常源于​​配置错误或环境冲突​​,而非端口修改本身,以下是系... 目录一、问题根源分析​​​二、保姆级解决方案​​​​步骤1:修正监听器配置文件 (listener.

Oracle 通过 ROWID 批量更新表的方法

《Oracle通过ROWID批量更新表的方法》在Oracle数据库中,使用ROWID进行批量更新是一种高效的更新方法,因为它直接定位到物理行位置,避免了通过索引查找的开销,下面给大家介绍Orac... 目录oracle 通过 ROWID 批量更新表ROWID 基本概念性能优化建议性能UoTrFPH优化建议注

PostgreSQL 序列(Sequence) 与 Oracle 序列对比差异分析

《PostgreSQL序列(Sequence)与Oracle序列对比差异分析》PostgreSQL和Oracle都提供了序列(Sequence)功能,但在实现细节和使用方式上存在一些重要差异,... 目录PostgreSQL 序列(Sequence) 与 oracle 序列对比一 基本语法对比1.1 创建序