如何通过OMS加快大表迁移至OceanBase
OMS,是OceanBase官方推出的数据迁移工具,能够满足众多数据迁移场景的需求,现已成为众多用户进行数据迁移同步的重要工具。OMS不仅支持多种数据源,还具备全量迁移、增量同步、数据校验等功能,并能够对分表进行聚合操作,例如将MySQL的分库分表数据通过OMS聚合到OceanBase数据库的单表中。
如需深入了解OMS的完整功能,请访问OceanBase的OMS文档进行进一步了解。
今日,我们的将主要介绍如何使用OMS迁移大表时,如何提升迁移速度。这在迁移历史库或归档库的数据时尤为重要,能够带来显著效益。接下来,我们将通过一个具体实例来探讨如何实现迁移过程的加速。
案例背景
最近遇到一个用户,使用 OMS 迁移 某数据到 OceanBase MySQL 模式,原表中的数据量大约有300+亿行,并且表存在longtext字段,这整体来看,是一个非常大的迁移工程,普通迁移也是至少耗时在周级别以上。用户在使用 OMS 迁移时,也遇到了很多问题:
- 原表中的表主键使用的是AUTO_RANDOM(5),这个是其源数据库特有的生成随机数方式,因为其分Region的方式是按range分,因此为了避免局部热点,需要随机生成。但是这样就导致一个问题,OMS在对源表进行切片时,效率非常差。
- OMS 在全量迁移时,会对表进行切片,根据主键的最大值和最小值,然后切分成多个分片分别进行迁移,因为表数据量非常大,导致分片数量非常多,影响迁移速度;
- OMS 日常迁移最快可以到30w行/秒,但是因为表中有longtext字段等原因,实测最多到1w行/秒,这样的迁移整体可能要超过1个月的时间;
- OMS 在写入目标端时,出现磁盘不足情况报错。
开始优化
问题1
首先,用户在 OMS 配置完迁移任务之后,发现迁移任务迟迟不开启同步,如下图,一直没有反应

这里因此对日志进行分析,查看 OMS 的 connetor.log 日志,发现在执行切片的 SQL 时,总是出现超时的报错,下面是报错的日志,日志的最后一条,就是执行切片的 SQL,可以看到会根据 id 字段进行一次排序。
The last packet successfully received from the server was 600,100 milliseconds ago. The last packet sent successfully to the server was 600,098 milliseconds ago.
460 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
461 at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
462 at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
463 at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
464 at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
465 at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:990)
466 at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3562)
467 at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3462)
468 at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3905)
469 at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2530)
470 at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2683)
471 at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2495)
472 at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1903)
473 at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2011)
474 at com.alibaba.druid.pool.DruidPooledPreparedStatement.executeQuery(DruidPooledPreparedStatement.java:227)
475 at com.oceanbase.oms.dataflow.jdbcclient.AbstractJDBCClient.nextSlicePkTop(AbstractJDBCClient.java:1438)
476 at com.oceanbase.oms.dataflow.jdbcclient.AbstractJDBCClient.nextSlicePkTop(AbstractJDBCClient.java:1473)
477 at com.oceanbase.oms.dataflow.slice.PkSliceService.lambda$slice$2(PkSliceService.java:207)
478 ... 6 common frames omitted
479 Caused by: java.net.SocketTimeoutException: Read timed out
480 at java.net.SocketInputStream.socketRead0(Native Method)
481 at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
482 at java.net.SocketInputStream.read(SocketInputStream.java:171)
483 at java.net.SocketInputStream.read(SocketInputStream.java:141)
484 at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:101)
485 at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:144)
486 at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:174)
487 at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:3011)
488 at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3472)
489 ... 17 common frames omitted
490 [2024-02-01 12:43:40.589] [INFO] [slice-worker-2] [SELECT `id` FROM `xxx`.`xxx` FORCE INDEX(`PRIMARY`) ORDER BY `id` ASC LIMIT 1]
这里为什么执行切片。OMS 的全量迁移逻辑,首先默认会对源表的主键找到最大值和做小值,然后每600条数据(sliceBatchSize参数控制) 做一个分片,这样源表会切成多个分片,然后并发地同步多个分片到目标端,这样可以加快整个同步的任务。
因为表的数据量非常大,并且主键是 AUTO_RANDOM(5),因此要进行一次排序执行时间会很长,OMS 切片查询默认超时时间是 10 分钟,超时之后又会重试,因此这个 SQL 基本是执行不出来,所以迁移任务迟迟没有办法启动。
可以看到,想通过 OMS 自动来做切片,基本比较困难,因此这里第一个优化就是人工介入进行手动切片,这块在全量迁移的参数管理里有几个参数,可以帮助我们进行手动进行切片
source."sliceByMinMax"=true
source."sliceMinMaxValue"=5342,17870283355246524268
source."sliceBatchSize":6000
- sliceByMinMax:设置为false,则表示人工手动设置最大值和最小值,而不是通过 SQL 去查;
- sliceMinMaxValue:设置主键 id 字段的最大值和最小值,这个我们自己可以根据 SQL 查询结果设置;
- sliceBatchSize:每个切片内的数据量
修改方式,在迁移任务的右上角-> 查看组件监控-> Full-Import 全量导入组件-> 点击更新,然后在source中加入这三个参数:

通过修改上面的参数,OMS 任务顺利运行起来了!
问题2
通过问题1的优化,虽然 OMS 迁移运行起来了,但是在执行一段时间之后发现,迁移任务又掉 0 了,并且持续时间很长

这里掉 0 之后,再次查看 connector.log 日志发现,因为我们手动设置了切片的最大值和最小值,而这个最大值和最小值相差比较大,所以在做分片的时候,因为很多切片区间是没有数据的,数据量为 0,所以在迁移这个切片时,实际没有数据迁移。
[2024-02-06 14:15:10.035] [INFO] [sourceTask-11] [xxx.xxx {xxx.xxx PK 13216115 [id:79296689342] - [id:79296695342]} rows : 0 , onNewBatchState:0.021]
实际这里 id 字段并不是连续递增的,因为 AUTO_RANDOM(5) 的缘故,导致表中 id 字段的最大最小值跨度非常大,但是小的值很多都是空的,所以 id 字段并不适合用来做切片。
因此是需要重新选择一个字段用来做切片的,经过对表结构分析,发现有个时间的字段比较适合来做切片 created double(20,8),字段保存的是:秒的时间戳+毫秒,用了double类型,时间精确到了毫秒,因为时间是连续的,并且跨度不大,基本每个时间段内都是有数据的,所以相比较来说是适合用来切片,并且上面有索引,切片查询是范围扫,不会太慢。
这里就需要另外修改一个参数,来指定切片使用这个字段
sliceIndex: {"库名.表名": "索引名:字段名"}
另外考虑到 sliceBatchSize 为 600,created字段每相差600秒内的数据量不能太大,否则每个切片数据量会比较大,迁移任务的jvm内存可能会撑爆。
因此重新调整参数之后如下:
source."sliceByMinMax"=true
source."sliceIndex"={"库名.表名": "索引名:created"}
source."sliceMinMaxValue"=1293595467,1707212258
source."sliceBatchSize":60

重新调整之后,恢复任务开始重新同步。
问题3
用户在遇到上面几个问题时,用的 OMS 版本还是4.2.1的版本,4.2.1 版本是不支持旁路导入的。旁路导入实际上是一个针对大表迁移的最优方式,旁路导入支持向 data 文件中直接写入数据,可以绕过 SQL 层的接口,直接在 data 文件中分配空间并插入数据,从而提高数据导入的效率,测试发现整体效率可以提升3-6倍。
这块因为在用户遇到这个问题时,OMS 4.2.2 版本即将发布,因此在让用户等了两天之后,将 OMS 升级到4.2.2 版本,开始使用旁路导入的方式。
旁路导入的配置也很简单,如下图,在配置 OMS 迁移任务时,在迁移选项中有个写入方式的选项,这里选择Direct Load方式,这样数据的迁移就会自动使用旁路导入的方式。

不过旁路导入这里有个问题,就是如果表中有数据,需要将数据清空之后再开始导入。即使旁路导入报错中断,如果要恢复迁移的话,也是需要重新清空表。
如何确认是否成功开启了旁路导入,这块可以在迁移任务的参数配置页面看到,如下图,出现direct.sink时,说明启动了旁路导入功能。

问题4
在任务开始一段时间后,OMS 收到报错

查看日志报错如下
[2024-02-21 05:37:06.473] [WARN] [sinkTask-27] [SyncSinkTask run ignore error, batch [com.oceanbase.oms.dataflow.common.stream.PartOfStreamRecordBatch
@67403183], cause [{}]]
java.lang.RuntimeException: Direct insert into "actions" failedat com.oceanbase.oms.connector.direct.sink.DirectPathWriter.flushRecords(DirectPathWriter.java:120)at com.oceanbase.oms.connector.direct.sink.DefaultDirectPathSink.offer(DefaultDirectPathSink.java:68)at com.oceanbase.connector.framework.threadmanager.sinktask.SyncSinkConnectorTask.run(SyncSinkConnectorTask.java:47)at java.lang.Thread.run(Thread.java:853)
Caused by: java.sql.SQLException: status : ERROR , error code : -4184at com.oceanbase.oms.connector.direct.sink.DirectPathConnection.insert(DirectPathConnection.java:233)at com.oceanbase.oms.connector.direct.sink.DirectPathPreparedStatement.executeBatch(DirectPathPreparedStatement.java:103)at com.oceanbase.oms.connector.direct.sink.DirectPathWriter.flushRecords(DirectPathWriter.java:95)... 3 common frames omitted
可以看到返回了4184的错误,查看 OceanBase 错误码,4184 的报错表示磁盘满了,实际这里只迁移了1亿多行,根据估算,是不能把磁盘写满的。
因此对每个磁盘的容量进行排查,发现每个 zone 只有 2 台机器上有流量,其他 4 台机器上基本没有写入流量,这里怀疑可能出现了数据的倾斜。但是这张表创建的是时候是做了分区,分区是均匀打散到所有机器上的,不应该出现倾斜。
继续排查发现,因为业务量随着时间不断增长,年份越近,数据量越大,分区打散虽然是按分区数量打散的,但是没有考虑到数据量的问题,可以看到2018年的数据量明显比2015年大很多。

而2018年的所有分区是集中在了一台机器上,导致这台机器的数据量非常大,这个是不符合预期的。经过验证,发现 OceanBase 目前在创建分区的时候,会以多个分区为一组,然后将这一组的分区集中到一台机器上,这个在range分区时有些不太合理。例如2018年按月有12个分区,一般情况下这12个分区应该在同一个zone中的6台机器上每台上有2个分区,同理2017年的分区也是这样。而实际时2017年的所有分区在一台机器上,2018年的所有分区在另一台机器上。这块和OceanBase官方确认之后,这块后续会做优化。
不过目前这种情况,有两种方式可以解决:
- 在创建二级分区,二级分区使用hash分区,进一步将分区打散;
- 手动迁移分区,迁移分区方式参考:Transfer Partition
因业务模型关系,这里无法做二级分区,否则会导致大量的跨机事务,因此只能选择手动迁移分区。
其他优化
优化1:
除了上面三个问题的解决,另外为了加快整体同步速度,这里还做了对JVM的调整,因为用户的 OMS 机器配置较高,所以默认的 JVM 参数无法全部发挥机器的性能。
调整 JVM 参数,同样也是在迁移任务的参数配置页面,修改如下
connectorJvmParam=-server -Xms64g -Xmx64g -Xmn60g -Xss512k
优化2:
当资源充分的情况下,也可以修改 source 和 sink 端的 workNum 数量,默认是8,这里也是修改成了32
source.workNum: 32
sink.workNum: 32
优化后收益
经过以上这些优化之后,这张大表的迁移实时流量基本达到了 1.5G/s,RPS最高可以达到 61w行/s,可以看到整体收效明显,如果迁移正常的话,基本2-3天就可以完成这张大表的迁移。

相关文章:
如何通过OMS加快大表迁移至OceanBase
OMS,是OceanBase官方推出的数据迁移工具,能够满足众多数据迁移场景的需求,现已成为众多用户进行数据迁移同步的重要工具。OMS不仅支持多种数据源,还具备全量迁移、增量同步、数据校验等功能,并能够对分表进行聚合操作&…...
讨论:WGS84与CGCS2000的坐标系怎么互转
前言: 今天我们要讨论一个问题:WGS84与CGCS2000的坐标系怎么互转? 对于有一定基础的朋友应该知道,WGS84和CGCS2000属于不同的椭球,如果进行严密的数学转换,是需要建立参数模型之后,再进行转换&…...
SpringCloud面试题
SpringCloud常见组件有哪些 注册中心组件:Eureka、Nacos 负载均衡组件:Ribbon 远程调用组件:OpenFeign 网关组件:Zuul、Gateway 服务保护组件:Hystrix、Sentinel 服务配置管理组件:SpringCloudConfig、Nac…...
深入了解Java Stream中的Collectors.partitioningBy()
在Java编程中,Stream API是一种强大的工具,它提供了处理集合数据的便捷方式。而Stream API中的Collectors.partitioningBy()方法则是其中一个十分有用的函数,它允许我们根据指定的条件将元素分成两个组。在本文中,我们将深入探讨这…...
下拉多选【bootstrap-multiselect】
1、引入资源 <link rel="stylesheet" href="${components}/bootstrap/css/bootstrap-multiselect.css"> <script src="${components}/bootstrap/js/bootstrap-multiselect.js"></script> 2、初始化 $("#topic-select&qu…...
建筑(八大员)报考条件
建筑八大员报考时间2024 建筑八大员每年考两次,上半年的考试时间一般在5-6月份,下半年的考试时间一般在10月左右。报名在考前2个月进行,2024年的考试时间和次数可能因省份而异,以住建厅通知为准。建筑八大员报考条件2024 1、年龄在18周岁以上(含18周…...
_remote.repositories作用
问题描述 明明我本地有某个依赖但是却还是报错,原因就是存在_remote.repositories且你的远程仓库中找不到该依赖,可能发生在你修改了远程仓库或镜像时。 例子 本地有这个依赖,但是报错。 解决 删除_remote.repositories文件࿰…...
2.3 Spark运行架构与原理
Spark运行架构由SparkContext、Cluster Manager和Worker构成。在集群模式下,Driver进程初始化SparkContext并向Cluster Manager申请资源,后者根据算法在Worker节点上启动Executor。Executor负责任务执行,反馈状态给Cluster Manager。任务由Ta…...
redis的跳表
typedef struct zskiplistNode {// 分值double score;// 成员对象robj *obj;// 后退指针struct zskiplistNode *backward;// 层struct zskiplistLevel {// 前进指针struct zskiplistNode *forward;// 跨度unsigned int span;} level[]; } zskiplistNode;跳表的节点查找算法可以…...
探索未知,开启海外盲盒新纪元——海外盲盒App,你的全球奇遇宝箱
一、引言 在快节奏、高压力的现代生活中,我们时常渴望一份来自未知的惊喜。为此,我们精心打造了一款全新的海外盲盒App,带你跨越地域界限,开启一场充满惊喜的全球奇遇之旅。 二、产品介绍 海外盲盒App是一款集购物、娱乐、文化…...
LeetCode2215找出两数组的不同
题目描述 给你两个下标从 0 开始的整数数组 nums1 和 nums2 ,请你返回一个长度为 2 的列表 answer ,其中:answer[0] 是 nums1 中所有 不 存在于 nums2 中的 不同 整数组成的列表。answer[1] 是 nums2 中所有 不 存在于 nums1 中的 不同 整数组…...
Git系列:git show 使用技巧
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...
python爬虫(五)之新出行汽车爬虫
python爬虫(五)之新出行汽车爬虫 接完最后一单,终于肝完了最后一个python爬虫——新出行爬虫,将https://www.xchuxing.com网站上所有的汽车爬虫全部抓取下来。 import requests import json import csv from lxml import etree …...
记录:卡尔曼滤波推导
参考:古月居-卡尔曼滤波 一、高斯分布(Gaussian Distribution) 一维高斯分布:随机变量 X X X服从数学期望 μ \mu μ、方差 σ 2 \sigma^2 σ2的正态分布,概率密度函数为 p ( x ) p(x) p(x)。 X ∼ N ( μ , σ 2 )…...
AI游戏外挂为何违法?
尊敬的读者们,大家好!今天我想和大家探讨一个备受争议的话题——AI游戏外挂的合法性。近年来,随着人工智能技术的飞速发展,AI外挂逐渐成为游戏领域的一大毒瘤。那么,为什么AI游戏外挂会被视为违法行为呢?本…...
UVa1006/LA2238 Fixed Partition Memory Management
UVa1006/LA2238 Fixed Partition Memory Management 题目链接题意输入格式输出格式 分析AC 代码 题目链接 本题是2001年icpc世界总决赛的G题 题意 早期的多程序操作系统常把所有的可用内存划分成一些大小固定的区域,不同的区域一般大小不同,而所有区域的…...
Autosar架构
蓝框那种叫component,绿框的叫function cluster。 接口 有三种接口,RTE跟SWC之间链接的叫Autosar Interface,RTE跟BSW的Components链接是Standardized Interface,RTE跟BSW的services链接的是Standardized Autosar Interface。 St…...
Java 异常介绍
在Java中,异常(Exception)是程序在运行时遇到的问题或错误的表示。异常可以是由程序错误、非法操作、资源不足或其他意外情况引起的。Java异常分为两类:受检异常(Checked Exception)和未检查异常(Unchecked Exception)。 受检异常(Checked Exception): 受检异常是编…...
vulhub靶机struts2环境下的s2-032(CVE-2016-3081)(远程命令执行漏洞)
影响范围 Struts 2.3.19至2.3.20.2、2.3.21至2.3.24.1和2.3.25至2.3.28 当用户提交表单数据并验证失败时,后端会将用户之前提交的参数值使用OGNL表达式%{value}进行解析,然后重新填充到对应的表单数据中。 漏洞搭建 没有特殊要求,请看 (3…...
Kubernetes之Headless Services
Kubernetes中的Headless Services(无头服务)是一种特殊类型的服务(Service)定义,它不提供传统意义上的负载均衡和集群IP地址分配。在无头服务中,spec.clusterIP 字段被显式设置为None ,Kubernet…...
OpenClaw移动端适配:Qwen3-14b_int4_awq通过Termux在安卓手机运行
OpenClaw移动端适配:Qwen3-14b_int4_awq通过Termux在安卓手机运行 1. 为什么要在手机上部署OpenClaw? 去年夏天的一个深夜,我正躺在沙发上刷手机,突然接到一个紧急需求:需要立即处理一批文件并生成报告。当时手边没有…...
Fix-Kindle-Ebook-Cover彻底解决Kindle电子书封面丢失问题:从根源修复到长效管理
Fix-Kindle-Ebook-Cover彻底解决Kindle电子书封面丢失问题:从根源修复到长效管理 【免费下载链接】Fix-Kindle-Ebook-Cover A tool to fix damaged cover of Kindle ebook. 项目地址: https://gitcode.com/gh_mirrors/fi/Fix-Kindle-Ebook-Cover Kindle电子书…...
OpenClaw异常处理:Qwen3-4B模型的任务失败恢复机制
OpenClaw异常处理:Qwen3-4B模型的任务失败恢复机制 1. 为什么需要关注OpenClaw的异常处理? 上周我让OpenClaw帮我整理一个月的会议录音转文字稿,结果第二天发现它卡在第七个文件就停止了。这种半途而废的情况在使用本地大模型时特别常见——…...
CefFlashBrowser终极指南:5个步骤让Flash内容在现代系统重生
CefFlashBrowser终极指南:5个步骤让Flash内容在现代系统重生 【免费下载链接】CefFlashBrowser Flash浏览器 / Flash Browser 项目地址: https://gitcode.com/gh_mirrors/ce/CefFlashBrowser 当Adobe在2020年正式终止Flash Player支持时,无数经典…...
SPIRAN ART SUMMONER企业集成:Java面试题中的AI应用解析
SPIRAN ART SUMMONER企业集成:Java面试题中的AI应用解析 掌握AI集成核心考点,轻松应对Java面试中的技术难题 1. 企业级AI集成面试要点 在Java技术面试中,SPIRAN ART SUMMONER这类AI模型的集成能力已经成为衡量候选人综合技术水平的重要标准。…...
CosyVoice多语言语音合成实测:中英文混合文本生成,自然流畅
CosyVoice多语言语音合成实测:中英文混合文本生成,自然流畅 1. 测试环境与模型介绍 1.1 测试硬件配置 本次测试使用的硬件环境如下: 组件规格GPUNVIDIA RTX 4090 (24GB)CPUIntel i9-13900K内存64GB DDR5操作系统Ubuntu 22.04 LTS 1.2 Co…...
如何检查网页标题是否符合 SEO 要求
如何检查网页标题是否符合 SEO 要求 在当今互联网时代,搜索引擎优化(SEO)已经成为每一个网站成功的关键要素之一。其中,网页标题的优化尤为重要。一个好的网页标题不仅能吸引用户点击,还能提高搜索引擎的排名。如何检…...
测试、项目管理、软件度量和质量
欢迎来到我的软考中级——软件设计师备考合集。这里不只是一份简单的知识点堆砌,而是我在备考征途中,对庞杂知识体系进行深度梳理与内化的结晶。 面对浩瀚的考纲,从计算机组成原理的底层逻辑,到操作系统的进程调度;从数…...
OpenClaw浏览器自动化:千问3.5-35B-A3B-FP8驱动智能爬虫实践
OpenClaw浏览器自动化:千问3.5-35B-A3B-FP8驱动智能爬虫实践 1. 为什么需要AI驱动的浏览器自动化 去年我接手了一个数据采集项目,目标是从几十个电商平台抓取商品信息和用户评价。传统爬虫在遇到验证码、动态加载内容时频繁失效,而人工操作…...
Windows下OpenClaw安装避坑:Gemma-3-12b-it接口对接详解
Windows下OpenClaw安装避坑:Gemma-3-12b-it接口对接详解 1. 为什么选择OpenClawGemma组合 去年第一次听说OpenClaw时,我正被重复性的文件整理工作折磨得焦头烂额。作为一个常年与Windows共处的开发者,我一直在寻找既能保护隐私又能实现办公…...
