一种Oracle->PolarDB全量数据校验的实现方法

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
简介: 本文主要介绍如何在Oracle迁移PolarDB过程中,如何做全量校验,以及实现原理。

本文主要介绍如何在Oracle迁移PolarDB过程中,如何做全量校验,以及实现原理。

背景

在交付大型OLTP迁移PolarDB的项目中,一般会要求做数据库一致性校验,用于确保数据一致性,这是做割接的前置条件。我们有很多种数据校验手段,常见的有全量校验、指标聚合校验、抽样校验、行数校验等,在实际的项目中我们一般会组合多种校验手段来完成数据校验。本文主要介绍Oracle迁移PolarDB的一种全量校验简易实现方式。

原理

数据同步原理

在政企客户的项目交付中,经常遇到大量无主键表的场景,我们使用ROWID来作为唯一键,来解决无主键表的数据一致性问题,DTS完整支持基于ROWID的迁移,逻辑如下:

image.png

数据校验原理

基于前文的数据同步原理,相应的也可以通过ROWID的唯一性来实现一致性校验,基于ROWID的顺序性和唯一性,我们完全可以通过rowid来切分数据,进行并行校验。

切分逻辑

对于大表,为充分利用CPU,我们一般把单表按照规则拆成多个任务并行校验。常见的切分逻辑,除了对有值部分的切分,还需要覆盖无值区间,不然会出现超出值区间的数据校验覆盖不到的问题,逻辑如下:

xxx1

但是这样的切分逻辑对oracle和polardb并不适用,理由是oracle 的rowid排序和polardb的rowid排序不是一个概念,oracle的排序是物理ROWID的顺序,而polardb的排序是基于ROWID字符串的排序,两者逻辑不等,且结果不一致。该问题导致我们没办法用相同的between逻辑来取数,同样也无法处理上图中的slice0 和slice 4 两种边界值的问题。所以重新设计切分逻辑,例如oracle minus polardb,按照下图设计切分逻辑。

image.png

在oracle侧基于oracle rowid顺序切分,然后在polardb侧,基于oracle查询的rowid list 获取对应数据,这样做避免了两边排序不一致带来的问题,在polardb侧切分也遵循同样的原理。在实现该切分方法时,还需要重点关注oracle的切分效率,常见的基于rowid排序分页会存在严重的性能问题,分页切片SQL如图:

set autotrace on;
select * from (select ROWID from zkk.demo where ROWID>'AAAaKSAAHAAAAGCAA0' order by "ROWID" )  where rownum<100;

执行计划如图

image.png

能看到发生了排序操作,存在性能问题,随着数据量和页数的推进,性能会越来越差,此时有两种方法解决该问题:

  1. 在本地缓存oracle ROWID,执行sql:select ROWID from tab order by ROWID asc,全表基于ROWID排序不会产生排序操作。然后把结果集存入本地文件,通过本地文件分段读取的方式进行切片。

  2. 在polardb端根据ROWID切分,字符串的排序不会出现排序性能的问题。

以上两种方式均能解决切分性能问题,但是遗留下另外一个问题,无法处理边界值问题,例如在polardb端切分,无法解决oracle比polardb数据多的问题,这个问题我们放到数据校验实现模块解决。

校验逻辑

理论上为校验A和B的数据一致性,我们一般做两次操作:A minus B;B minus A。这样既能解决存量数据对比,也能解决在前文提到的数据边界问题。但是在实际工程实现上,两次minus操作存在大量的重复计算,且minus效率低。所以我们把minus转换成hash join,ROWID作为join键,只做一次正向对比,然后在对比一次A和B的数据行数即可。如果A hash join B 一致 ,且A和B 数据行数一致,我们认为全量对比一致。本文主要介绍全量比对,不对行数比对做过多介绍,接下来介绍下怎么用最简单的办法实现全量数据校验。

我们使用spark来解决数据的抽取和校验,能节省大量的编码工作。在切分策略上选择基于Oracle进行切分,这样做的原因是如果基于PolarDB切分,那么就需要在oracle做where "ROWID" in的操作,Oracle限制IN的条数不超过1000,而PolarDB没有这个限制,选择Oracle切分可避免该问题。按照生产者消费者逻辑进行程序设计,整体逻辑如下图:

image.png

对于大部分的场景,我们都可以复用spark的数据结构来解决结果集的对比问题,但是依然存在一些问题需要解决。在Oracle迁移PolarDB过程中,需要特别关注浮点数类型,浮点数类型一般都做了相应的转换,例如源库binary_float类型,目标库转化为double;源库float类型,目标库转化为real,我们需要在spark层把数据类型统一。

binary_float 转化为double,理论上double比binary_float精度更高,所以我们需要从双精度转换成单精度,才能正常校验binary_float类型。

#使用spark本身的能力,把polardb结果集中的double转换成float
ds=ds.withColumn(columnDefineDO.getColumnName(), ds.col(columnDefineDO.getColumnName()).cast(FloatType$.MODULE$));

float转化为real,理论上oracle的float是基于number实现,所以jdbc读取后的类型是BigDecimal,polardb 的real 类型在jdbc读取的类型是double,我们把double转换成BigDecimal。我们知道float(n) ,n的含义并不是10进制意义上的位数, 是二进制有效位数,我们在转换成成BigDecimal时要注意位数转换,转换公式:precision*0.30103,取整数位。

#使用spark本身的能力,把polardb结果集中的real转换成BigDecimal
int precision=new Double(floatPrecision*0.30103).intValue();

ds=ds.withColumn(columnDefineDO.getColumnName(), ds.col(columnDefineDO.getColumnName()).cast(new DecimalType(38,precision)));

关注内存使用,注意配置批量拉取的行数,因为是多线程环境,数据需要放到内存中比对,数据量越大内存消耗越大,我们必须关注OOM风险。当前的设计架构只支持调整批量数据条数来控制内存,实际上这种方式存在缺陷,当遇到单行数据过大的场景,依然会出现OOM问题,最佳的方式是根据表的存储大小和表行数,来估算最佳的批量读取行数。

结果统计

最后我们做好数据统计,除了统计不一致的数据条目,还需要记录不一致数据的ROWID,方便问题的定位和排查。

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
9天前
|
Oracle 安全 关系型数据库
Oracle数据恢复—Oracle数据库误删除的数据恢复方法探讨
删除Oracle数据库数据一般有以下2种方式:delete、drop或truncate。下面针对这2种删除oracle数据库数据的方式探讨一下oracle数据库数据恢复方法(不考虑全库备份和利用归档日志)。
|
2月前
|
Oracle 安全 关系型数据库
|
2月前
|
关系型数据库 分布式数据库 数据库
PolarDB产品使用问题之如何进行PostgreSQL(简称PG)的全量和增量备份管理
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
2月前
|
Oracle 关系型数据库 数据库
|
2月前
|
存储 Oracle 关系型数据库
|
2月前
|
SQL Oracle 关系型数据库
关系型数据库Oracle设置 RMAN 环境:
【7月更文挑战第25天】
54 2
|
2月前
|
存储 Oracle 关系型数据库
关系型数据库Oracle运行RMAN脚本
【7月更文挑战第23天】
40 4
|
2月前
|
SQL Oracle 关系型数据库
关系型数据库Oracle结束 RMAN 会话:
【7月更文挑战第25天】
49 1
|
2月前
|
监控 Oracle 算法
|
2月前
|
Oracle 关系型数据库 数据库
关系型数据库Oracle编写RMAN脚本
【7月更文挑战第23天】
34 2