配置常见问题
如何获取导数工具软件包?
OceanBase 软件下载中心 > 社区版 > 迁移工具 > OceanBase 导数工具 > 选择版本并下载。
导数工具支持哪些 OceanBase 版本号?如何根据 OceanBase 版本选择合适的导数工具版本?
导数工具版本号与 OceanBase 的前两位版本号存在对应关系。例如:导数工具 4.2.x 支持 OceanBase 4.2.0 及之前的版本。新版本的导数工具会兼容之前版本支持的 OceanBase,所以除了某些新引入且无法绕开的问题,建议使用最新版本的导数工具。
商业版和社区版导数工具有什么区别?
导数工具 4.2.1 之前的版本兼容的 OceanBase Connector-J 尚未开源,导数工具根据使用的 JDBC 版本区分商业版和社区版(社区版使用的 JDBC 驱动为 mariadb 官方驱动,无法支持 OceanBase ORACLE 租户);导数工具 4.2.1 及之后的版本兼容的 OceanBase Connector-J 已经开源,因此不再区分商业版和社区版,可以从 OceanBase 软件下载中心 > 社区版中下载导数工具包。
导数工具使用的 JDBC 驱动版本是什么?如何自行替换 JDBC 驱动?
不同版本的导数工具,其使用的 JDBC 驱动版本也不同。
导数工具 4.2.1 ~ 4.2.4 使用 OceanBase Connector-J 2.4.3;
导数工具 4.2.5 ~ 4.2.6 使用 OceanBase Connector-J 2.4.5;
导数工具 4.2.7 使用 OceanBase Connector-J v2.4.7.1。
您可以在 {ob-loader-dumper}/lib 目录下自行替换不同版本的 OceanBase Connector-J jar。
什么情况需要提供 sys 租户?云数据库 OceanBase 环境是否必须要指定 --public-cloud 选项?
OceanBase 4.0.0 之前的版本必须使用 --sys-password 选项或者 --no-sys 选项以指定程序是否依赖 sys 租户。缺少 sys 租户可能会导致导出结构定义不全,或者在导入时无法计算分区。这是因为某些系统视图仅 sys 租户可见。
OceanBase 4.0.0 之后的版本已完全不依赖 sys 租户,使用时无需指定 --sys-password 或者 --no-sys 选项。
云数据库 OceanBase 环境下必须指定 --public-cloud 选项,需注意,OceanBase 4.0.0 之前的版本使用 --public-cloud 选项时,默认不依赖 sys 租户,因此无需指定 --sys-password 或者 --no-sys 选项。
导数工具能否配置 OceanBase 会话变量,以及 JDBC URL Options?
导数工具 4.2.6 之前的版本仅支持有限的会话变量与 JDBC 参数,您可以通过 {ob-loader-dumper}/conf/session.properties 修改已有的配置项。
导数工具 4.2.6 及之后的版本的配置文件({ob-loader-dumper}/conf/session.config.json)提供更灵活的配置方式,对于 OceanBase 支持的 SQL 语句或者 JDBC 支持的 URL 参数,您可以不受限制对已有的连接参数进行增、删、改。具体请参见 导数工具连接配置。
在控制台中输出日志时无响应,该如何解决?
可能是控制台输出被暂停或中止,导致日志输出被阻塞。解决方法:
打开日志的配置文件
{ob-loader-dumper}/conf/log4j2.xml,查找如下配置:<Logger name="com.oceanbase.tools.loaddump" additivity="false" level="INFO"> <AppenderRef ref="ConsoleAppender"/> <AppenderRef ref="InfoRoutingAppender"/> <AppenderRef ref="WarnRoutingAppender"/> <AppenderRef ref="ErrorRoutingAppender"/> </Logger>删除
<AppenderRef ref="ConsoleAppender"/>,并尝试重新运行程序。
如何自定义导入作业日志文件名?
可以在 {ob-loader-dumper}/conf/log4j2.xml 中自定义日志文件名。如下图所示,在 Routing 标签下修改如下名称:
InfoRoutingAppender下的ob-loader-dumper.info(info 级别日志)。WarnRoutingAppender下的ob-loader-dumper.warn(warn 级别日志)。ErrorRoutingAppender下的ob-loader-dumper.error(error 级别日志)。
说明
将 ob-loader-dumper.info、ob-loader-dumper.warn、ob-loader-dumper.error 修改为相同名称时,所有日志信息会生成到同一文件中。

导数工具如何自定义日志打印级别?
您可以使用文本编辑器打开导数工具包中的 {ob-loader-dumper}/conf/log4j2.xml 文件。具体操作步骤:
将 Configuration > Loggers > name=com.oceanbase.tools.loaddump 的 Logger > 设置 level 为所需的日志打印级别。支持以下级别:DEBUG, INFO, WARN, ERROR。同时您可以在 Loggers 下更改其他组件的日志配置。
示例:将导数工具的日志打印级别设置为 DEBUG。
<Logger name="com.oceanbase.tools.loaddump" additivity="false" level="DEBUG">
<AppenderRef ref="ConsoleAppender"/>
<AppenderRef ref="InfoRoutingAppender"/>
<AppenderRef ref="WarnRoutingAppender"/>
<AppenderRef ref="ErrorRoutingAppender"/>
</Logger>
如何打开 jdbc-io 的 trace 日志?
首先设置 JDBC 参数 log=true。
添加以下 Logger 至 Loggers:
<logger additivity="false" level="trace" name="com.oceanbase.jdbc.internal.io"> <AppenderRef ref="JdbcTraceAppender"/> </logger>添加以下 Routing 至 Appenders。
<Routing name="JdbcTraceAppender"> <Routes pattern="$${ctx:task.workspace}"> <Route> <RollingFile name="InfoRolling-${ctx:task.workspace}" immediateFlush="false" fileName="${ctx:task.workspace}/jdbc-io.log" filePattern="${ctx:task.workspace}/${date:yyyy-MM}/jdbc-io-%d{yyyy-MM-dd}-%i.log.gz"> <PatternLayout> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </PatternLayout> <Filters> <!-- TRACE < DEBUG < INFO < WARN < ERROR < FATAL --> <ThresholdFilter level="TRACE" onMatch="ACCEPT" onMismatch="DENY"/> </Filters> <Policies> <TimeBasedTriggeringPolicy interval="6" modulate="true"/> <SizeBasedTriggeringPolicy size="256 MB"/> </Policies> </RollingFile> </Route> </Routes> </Routing>
如何控制程序所占内存?
通过编辑器打开 {ob-loader-dumper}/bin/obloader,查找关键字 -Xms 与 -Xmx,前者表示 JVM 初始化堆内存,后者表示 JVM 最大可申请的堆内存。
定时打印的性能监控日志里的指标分别是什么含义?
Enqueue performance 为生产端,即解析文件的性能指标; Dequeue performance 为消费端,即写入数据库的性能指标。更多详情请参见OBLOADER 工作原理。
其中,1.sec.avg 表示全局平均吞吐,1.min.avg 表示最近一分钟的平均吞吐。
数据处理常见问题
如何使用 OBLOADER 导入与表不同名的数据文件?
命令行中的 -f 选项指定为数据文件的绝对路径。例如:--table 'test' -f '/output/hello.csv'。
什么是 ETL?如何使用导数工具的 ETL 能力?
数据库 ETL 工具是用于将数据从一个数据库移动到另一个数据库的工具。ETL 代表提取(Extract)、转换(Transform)和加载(Load),表示从源数据库提取数据、将转换后的数据加载到目标数据库的过程。由于导数工具的工作场景并非在线迁移,因此导入时 “Extract” 的对象与导出时 “Load” 的对象,皆为文件系统或其他存储介质,而非源/目标数据库。“存储介质” 表示包括本地文件系统在内的多种存储系统,例如 Aliyun OSS,Amazon S3 和 HDFS。
导数工具同时通过丰富的命令行选项与控制文件来支持 “Transform” 能力。
OBLOADER 中的 Block Size (--block-size)是指什么?
A:Block Size 指对大文件进行逻辑切分的子文件大小,以 'MB' 为单位,默认是 64 MB。具体请参见OBLOADER 如何执行对大文件的逻辑切分?。
导入结构时,--mix 与 --ddl 有什么区别?
仅导入从 OBDUMPER 导出的结构定义(含完整的目录结构)时,需要使用 --ddl 选项。否则使用 --mix 选项。 Mix 模式下,导数工具支持导入的 SQL 文件类型:
mysqldump 导出的 SQL 文件。
同时包含 DDL 与 DML 的 SQL 文件。
包含 MySQL 原始表结构定义的文件(仅导数工具 4.2.7 及之后的版本支持)。
CSV 与 CUT 格式有什么区别?
CSV 格式具有以下特征:
列分隔符须为单字符。
大多数情况下存在定界符(即数据两边是否有引号)。
大多数情况下包含 Header。
CUT 格式是一种类似 CSV 的较为灵活的格式,具有以下特征:
列分隔符可以为单字符或者多字符。
不存在定界符。
不包含 Header。
CSV 与 CUT 格式的列分隔符是特殊字符怎么办?
导数工具支持以 HEX 表示方式输入特殊字符。例如:'\t' 的 HEX 表示 '0x09';'Ctrl+O'('^O')的 HEX 表示为 '0x0F'。
运行 OBLOADER 脚本时,何时需要对参数加单引号或者双引号?
建议用户在一些字符串的参数值左右加上相应的引号。
Windows 平台参数使用双引号。例如:
--table "*"。类 Linux 平台参数使用单引号。例如:
--table '*'。
如何选择性地导入某些表或某些列?是否支持黑白名单?
白名单:--table,--include-column-names(有序)。
黑名单:--exclude-tables, --exclude-column-names,--exclude-data-types。
注意
同类型的黑白名单不能混用。
如何控制程序的并发度?--thread 与 --parallel 有什么区别?
您可以通过 --thread 选项设置客户端并发度,--parallel 选项设置服务端并发度。
客户端并发度是指导数工具自身可以调用的线程数,默认情况下,
--thread的值为 CPU 逻辑核数 * 2。其作用范围包括但不限于:客户端连接池的大小。
客户端模式下导入时,生产者和消费者的数量、解析文件的并发度、查询元数据的并发度。
服务端模式下导入时,同时处理的表数。
服务端并发度是指 OBServer 在处理客户端请求时使用的并发度。事实上,
--parallel是一个直接透传给 OBServer 的参数。--parallel默认值为 1。目前,其作用范围包括:服务端逻辑导入的总体并发(参考 LOAD DATA
parallel hint)。服务端旁路导入的总体并发(参考 LOAD DATA
parallel hint)。客户端旁路导入时用于排序的线程数。
命令行选项 --replace-data 与 --replace-object 有什么区别?作用机制是什么?
--replace-data指替换表中的数据。MySQL 模式下,程序通过替换 INSERT 语句为 REPLACE INTO 语句实现替换。
Oracle 模式下:
OBServer 2.2.76 之后的版本:程序通过替换 INSERT 语句为 MERGE INTO 语句实现替换。
OBServer 2.2.76 之前的版本:程序通过 “先删后插” 实现替换。
--replace-object指替换对象结构。程序会从执行语句中解析出对象名,在执行实际语句时捕获“同名对象异常”,并尝试先 DROP 该对象,再执行实际 DDL 语句。
如何编写控制文件?控制文件为什么不生效?
控制文件表示一个数据库表中的列与原始数据文件中的列之间的映射关系。有关控制文件与数据库表、原始数据文件之间的关系,请参见 定义控制文件。
场景一:控制文件中每一行与文件列一一对应
示例:使用 OBLOADER 导入 order 表数据时,通过控制文件 order.ctrl 映射文件 order.txt 中表的列,控制文件中每一行与文件列一一对应。

控制文件中每一行都必须为存在的数据库表列名,而 map 函数中的参数为原始数据文件的列偏移量。例如控制文件 order.ctrl 中的 id map(1) 表示 order.txt 中的第 1 列对应 order 表中的 id 列。
控制文件中您可以不填写 map 关键字,此时默认的映射关系满足:控制文件中自上而下,文件列自左到右,一一对应。
上述示例仅为一种理想情况。在这种能够自上而下一一完美对应的条件下,您甚至无需声明控制文件。控制文件的作用旨在进行列筛选。
场景二:表中包含自动递增列
示例:使用 OBLOADER 导入包含 id 自增列的 order 表数据时,通过控制文件 order.ctrl 映射文件 order.txt 中表的列。
因 id 为自增列,文件 order.txt 中可能不会存在与 id 对应的列。此时,仅需要删除控制文件中对 id 的声明。

场景三:修改表中多个列
示例:使用 OBLOADER 导入 order 表数据时, order 表中新增列 item_id 和删除列 identified_id,通过控制文件 order.ctrl 映射文件 order.txt 中表的列。
order 表中的最近有业务更改,新增列 item_id 且删除了列 identified_id,则 order.txt 中可能会存在与 identified_id 对应的列,而缺少与 item_id 相关的列。此时,仅需按照 map 定义选择需要的数据文件列:
如果需要将缺失的列
item_id设置为一个定值,可以使用生成函数 constant。有关生成函数,请参见本篇文档中的 预处理函数为什么不生效。如果需要使用数据库内定义的默认值,可以直接删除控制文件中对
item_id的声明,以在导入时忽略列item_id。

预处理函数为什么不生效?
预处理函数包含替换函数与生成函数,生成函数目前仅包括:constant, sequence, db_sequence,其它均为替换函数。若控制文件中对某一列声明了生成函数,则无需对应任何文件列。例如:c1, c2 "constant('a')", c3,表示数据库表中的 c1、c3 列,分别对应文件中的第一列、第二列。
示例:
# create table t_ctrl(c1 int, c2 int, c3 int)
# 待导入 CSV 文件有三列
# c1 为文件第一列,c2 为文件第二列, c3 为文件第三列
lang=java(
c1,
c2,
c3
);
# create table t_ctrl(c1 int, c2 int, c3 int)
# 待导入 CSV 文件有三列
# c1 为文件第二列,c2 为文件第三列, c3 为文件第一列
lang=java(
c1 map(2),
c2 map(3),
c3 map(1)
);
# create table t_ctrl(c1 int auto increment, c2 int, c3 int default NULL)
# 待导入 CSV 文件有三列
# c1 为自增列, c2 为文件第二列, c3 默认值(NULL)
lang=java(
c2 map(2)
);
# create table t_ctrl(c1 int, c2 int, c3 char(3), c4 int)
# 待导入 CSV 文件有三列
# c1 为文件第一列,c2 为文件第二列, c3 直接生成常量, c4 为文件第三列
lang=java(
c1,
c2,
c3 "constant('abc')"
c4
);
对于控制文件不生效的排查一般需要观察程序运行日志。在控制文件解析阶段,程序会对 --ctl-path 路径下的控制文件进行筛选。以下不同的日志对应不同的行为:
The control file is unexpected, ignore it:说明该控制文件并不与任何一张表相关联。The control file is invalid, ignore it:说明该控制文件语法定义不合法。Parse ctrl definition: success:说明控制文件解析成功,并与其相关联的表绑定。
函数不生效的排查方向,关注以下两点:
map 关键字的使用。文件列是否能一一对应上数据库表列?
列名大小写问题。OBLOADER 4.2.0 之前的版本支持区分列名大小写,而 OBLOADER 4.2.0 及之后的版本不支持区分。在数据库设置了大小写敏感的场景,需要在每个列名外加一层中括号,来表示“大小写敏感”。
错误处理常见问题
为表配置了控制文件,导入的数据为什么没有生效?
要求控制文件的名称与表名相同且大小写一致。MySQL 默认表名为小写,Oracle 默认表名为大写。
外部文件格式不符合要求导致导入失败,应该如何解决?
导入外部文件时对格式有以下要求:
外部文件如果为 SQL 文件,要求 SQL 文件中不能有注释和 SET 开关语句等,并且文件中只能有 INSERT 语句,每条语句不可以换行。除此以外,文件中存在 DDL 或者 DML 语句,建议使用 MySQL source 命令导入。
外部文件如果为 CSV 文件,CSV 文件需符合标准定义。要求有转义符、定界符、列分隔符和行分隔符。数据中存在定界符需要指定转义符。
如何解决使用 OBLOADER 导入时遇到 OOM 错误?
首先修改 bin/obloader 脚本中的 JAVA 虚拟机内存参数。其次排除 OpenJDK GC Bug。
如何在调试模式下运行 OBLOADER 排查问题?
直接运行 bin/obloader-debug 进行导入。
报错信息太简短,如何获取更详细的错误堆栈?
您可以使用导数工具包中的 obloader-debug 重新执行命令,最后的报错信息会包括完整的堆栈。如果您根据详细的错误信息仍无法解决问题,可以将其以文本形式或截图发送到阿里钉 “离线导数支持群” 以获取研发支持。
程序好像卡住了,应该如何解决?
首先,某些低版本的 JDK 有 GC 缺陷,会导致程序卡住。推荐您使用 JDK 1.8.0_301 及之后的版本。
其次,程序可能是执行某些步骤较为缓慢,并非卡住,您可以修改日志输出级别为 DEBUG 级别并重新运行程序来确认是否无响应(hang 住)。具体请参考本篇文档中的导数工具如何自定义日志打印级别。如果可以确定使用的 JDK 版本在推荐区间内,且程序确实无响应(hang 住),可以通过 jstack 工具采集 Java 进程的实时堆栈信息并寻求研发支持。
采集堆栈信息方法如下:
通过执行命令
jps -l列举出当前所有 Java 进程。查询进程名包含
Obloader或Obdumper的进程,记录其 pid。执行命令
jstack -l pid > jstack.log。jstack.log即为采集到的堆栈信息。
注意
pid 必须为 Java 进程,而非导数工具包 bin 目录下的 shell 脚本。
程序为什么突然异常终止?日志未显示 “System exit 1”。
如果进程突然结束,极大概率是进程被系统关闭。请关注您的运行环境是否为虚拟容器。以 Docker 为例,Docker 会关闭资源占用率超标的容器进程,当出现此类情况时,请首先参考OBLOADER 性能调优,合理降低进程的资源占用。
运行 OBLOADER 脚本时,命令行选项未被正常解析的原因是什么?
可能是命令行参数值中存在特殊符号。例如:Linux 平台上运行导数工具,密码中存在 '>'(注:'>' 为重定向符),导致运行的日志都会出现丢失。解决方法:
首先可以查看日志,程序往往会提供成功解析出的参数列表,由此,您可以判断哪些命令行参数值中存在特殊字符导致命令被错误解析。
建议为字符串类型的命令行选项的值加引号。例如:-p &^%$#@ 更改为 -p '&^%$#@'。
OBLOADER 导入数据时报错:Unexpected end of stream、Connection is reset、Connection is closed。
此类报错表示服务端将连接中断了。您连接的服务端可能是 ODP 或 OBServer,也可能是 F5 或其他负载均衡中间件。解决方法:
首先,您可以通过监控、运维平台查看有无服务端的报警;如果无报警,则考虑查看服务端的日志。以 ODP 为例,查询与导数工具报错时间点吻合的 WARN 或 ERROR 日志,然后确认服务端断连的具体原因。如无日志,则可能是 ODP 由于某些故障发生了重启。
OBLOADER 导入数据时报错:Connection is timeout、Read timeout。
此类报错表示客户端等待服务端响应超时(Socket timeout)。Socket timeout 由 JDBC 参数 "socketTimeout" 控制,默认为 30 分钟。如何更改 JDBC 参数请参见本篇文档中的 如何打开 jdbc-io 的 trace 日志。解决方法:
首先,OBLOADER 4.2.3 之前的版本存在缺陷,JDBC 参数 "socketTimeout" 默认为 10s。请考虑升级版本。
大多数情况下,服务端不会耗时 30 分钟处理请求。大概率是发生了丢包(服务端无回包或客户端未确认收包),请先提供 ODP 及 OBServer 在相关时间点的日志,并寻求研发人员支持。
OBLOADER 导入数据时报错:The system config open_cursors value may be not enough。
该报错表示 OBServer 系统参数 open_cursors 可能过小(一般小于导数工具默认的并发度,具体请参见本篇文档中的 如何控制程序的并发度。解决方法:
首先查询现有的 open_cursors 数量,并执行以下 SQL 调大 open_cursors:
alter system set `open_cursors`=?。
OBLOADER 导入数据时报错:java.lang.OutOfMemoryError: Java heap space。
该报错表示 JVM 堆内存超限。默认的 JVM 最大堆内存是 4GB,我们推荐您设置 JVM 内存为客户端机器可用内存的 60% 左右。解决方法:
通过编辑器打开 {ob-loader-dumper}/bin/obloader,查找关键字 -Xms 与 -Xmx,前者代表 JVM 初始化堆内存,后者代表 JVM 最大可申请的堆内存。同时,考虑适当调低 --thread 从而降低并发度。如仍无法解决问题,请将工作目录下 jvm 自动导出的 '.hprof' 文件发给研发,并描述您的使用场景。
OBLOADER 导入数据时报错:Transaction Timeout。
执行 DML 或 DDL 超时,大部分情况下出现在导入结构定义(DDL)时。解决方法: 调整会话变量,修改 ob_trx_timeout 的值。具体请参见本篇文档中的导数工具能否配置 OceanBase 会话变量。
OBLOADER 导入数据时报错:Access denied for user 'root'。
如您 -u 指定的不为 root 用户,这是因为程序连接 OBServer 4.0.0 之前的版本时,需要 sys 租户信息。解决方法:请参见本篇文档中的什么情况需要提供 sys 租户。
OBLOADER 导入数据时显示 WARN 级别日志:Treat it as non-partition table,或者 ERROR 级别日志:Invalid table entry:xxx。
请参见 分区计算失败会怎样。解决方法:
OBServer 4.0.0 之前的版本,可能是因为您未提供 sys 租户的帐密。
OBServer 4.0.0 及之后的版本,可能是因为您未提供租户名(
-t选项)或集群名(-c选项)。
注意
OBDUMPER 4.2.7 及之前的版本都无法识别三段式的用户名。例如:不支持 -uroot@tenant@cluster,您需要改成 -u root -t tenant -c cluster。
导入 CSV 文件且数据内存在换行时,OBLOADER 运行报错:Bad Record。
可能是 OBLOADER 默认使用了 UNSAFE 模式切分子文件。需要修改执行脚本中的 JVM 环境变量。打开 {ob-loader-dumper}/bin/ 目录下的 obloader 文件,查找关键词 PROG_OPTS 并将 -Dfile.split=UNSAFE 修改为 -Dfile.split=SAFE。
OBLOADER 运行报错:Over tenant memory limits 或者 No memory or reach tenant memory limit。
调大全局 SQL 工作区的内存比例或者减少 --thread 并发数。
set global ob_sql_work_area_percentage=30; -- Default 5
OBLOADER 运行报错:No tables are exists in the schema: "xxx"。
--table 't1,t2' 选项指定的表名一定是数据库中已经定义的表名,且大小写需要保持一致。OceanBase MySQL 模式下默认表名为小写,OceanBase Oracle 模式下默认表名为大写。如果 Oracle 中定义的表名为小写,表名左右需要使用中括号。例如:--table '[t1]' 表示小写的表名。
OBLOADER 运行报错:The xxx files are not found in the path: "xxx"。
要求 -f 指定的目录中的数据文件的名称与表名相同且大小写一致。OceanBase MySQL 模式下默认表名为小写,OceanBase Oracle 模式下默认表名为大写。例如:--table 't1'目录中的数据文件须为 t1.csv 或者 t1.sql,不能是 T1.csv 或者其它的文件名。
OBLOADER 运行报错:The manifest file: "xxx" is missing。
元数据文件 MANIFEST.bin 是 OBDUMPER 导出时产生的。使用其它工具导出时没有元数据文件。用户指定 --external-data 选项可跳过检查元数据文件。
OBLOADER 运行报错:Not supported feature or function。
低版本的 OBServer 不支持某些特性。使用 OBServer 2.2 及之前的版本时,请将 {ob-loader-dumper}/conf/session.config.json 文件中的 JDBC 参数 useServerPrepStmt 设置为 false,并删除 init_sql.mysql 标签下 set session sql_mode = xxx 语句。
OBLOADER 导入 Delimited Text 格式时报错:Index:0,Size:0。
出现这种错误的原因是数据中存在回车符/换行符,请先使用脚本删除数据中的回车符/换行符后再导入数据。
OceanBase MySQL 模式下,连接 ODP (Sharding) 逻辑库导入 KEY 分区表数据时,OceanBase Database Proxy (ODP) 显示内存不足且 OBLOADER 运行报错:socket was closed by server。
设置 proxy_mem_limited 参数的权限,确认是否有外部依赖,ODP 默认内存限制为 2GB。连接 ODP (Sharding) 逻辑库且通过 OBLOADER 导入数据时需要使用 root@proxysys 账号权限,修改逻辑库内存限制语句如下:
ALTER proxyconfig SET proxy_mem_limited = xxg
性能调优常见问题
说明
调优前,我们强烈推荐您先阅读 OBLOADER 工作原理。
OBLOADER 导入数据慢?吞吐低?
OBLOADER 导入时的步骤主要包括:
生产者从数据源加载数据到内存(本地磁盘、对象存储、HDFS 等)。
生产者解析数据并发往 Ring Buffer。
消费者从 Ring Buffer 获取数据,并通过 SQL 协议(逻辑)或 RPC 协议(旁路)写入数据库。
(仅旁路)服务端进行数据排序并构建索引。
将瓶颈粗略地划分为生产端瓶颈与消费端瓶颈,这有助于快速定位瓶颈所在。
生产端的吞吐受哪些因素影响?从数据源加载的吞吐(例如 OSS 的读速率),解析文件的性能(解析 CSV 、CUT 比 Parquet、 ORC 快速),以及以上二者的并发度。
消费端的吞吐受哪些因素影响?事务处理性能(逻辑导入);OBKV 的 RPC 吞吐与服务端处理时间(旁路导入)。
如何确认是生产端瓶颈还是消费端瓶颈?
导数工具提供了一个参数用于跳过入库流程,您可以通过编辑器打开 {ob-loader-dumper}/bin/obloader,查找关键字 -Ddry.run(导数工具 4.2.7 之前的版本关键字为 -Ddisable.import),将其设置为 'true' 并重新执行程序,观察此时的吞吐并与之前进行对比。如果吞吐无显著变化,则为生产端瓶颈。反之,则为消费端瓶颈。
生产端瓶颈解决思路:
您需要了解文件逻辑切分的机制。程序无法切分二进制格式的文件(ORC 与 Parquet),从而无法利用并发来提高整体的解析性能。您可以考虑手动将大文件物理拆分成一个个的小文件,从而提高解析性能。具体请参见 OBLOADER 如何执行对大文件的逻辑切分。
考虑是否并发度不足。考虑提高
--thread的值,以提高同时处理的文件数量。如果 CPU 占用率始终较高,则说明是机器的 CPU 处理能力已经达到瓶颈,您可以考虑升高客户端机器的规格。考虑是否分配的 JVM 内存不足。JVM 内存会影响 Ring Buffer 的大小。默认的 JVM 最大堆内存为 4GB,我们推荐您设置 JVM 内存为客户端机器可用内存的 60% 左右。通过编辑器打开
{ob-loader-dumper}/bin/obloader,查找关键字-Xms与-Xmx,前者代表 JVM 初始化堆内存,后者代表 JVM 最大可申请的堆内存。
消费端瓶颈解决思路:
考虑是否并发度不足。您可以提高
--thread的值,或者设置--rw来增加消费者的数量。如果是逻辑导入,可能是事务执行性能不佳,您可以通过运维或监控平台查看事务的 TPS 与 RT,并通过常见的调优手段来判断问题原因。例如,对于拥有一个或多个索引的表,在相同环境下,其执行写入的性能会低于不包含索引的表。
目前最常见的导致事务处理性能下降的原因是:频繁的转储。您可以通过设置系统参数:
freeze_trigger_percentage来提高转储阈值,从而降低转储频率。注意
在生产环境更改系统参数或其他运维参数属于风险操作,操作前请先咨询 DBA。
如果您使用的是旁路导入,我们暂时未遇到旁路吞吐低的问题反馈,如遇到此类问题请反馈给研发人员。