---
title: OBDUMPER 常见问题-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于 OBDUMPER 常见问题相关的常见问题和使用技巧，帮助您快速解决 OBDUMPER 常见问题的难题。
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

划线反馈

# OBDUMPER 常见问题

更新时间：2025-06-20 08:16

适用版本： V3.0.x、V3.1.x、V3.2.x、V3.3.x、V4.0.x、V4.1.x、V4.2.x 内容类型：FAQ  

## 配置常见问题

### 如何获取导数工具软件包？

[OceanBase 软件下载中心](https://www.oceanbase.com/softwarecenter) > 社区版 > 迁移工具 > 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 2.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 参数，您可以不受限制对已有的连接参数进行增、删、改。具体请参见 [导数工具连接配置](https://www.oceanbase.com/docs/common-oceanbase-dumper-loader-1000000000381187)。

### 如何自定义导出作业日志文件名？

可以在 `{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` 修改为相同名称时，所有日志信息会生成到同一文件中。

![logs](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/obloaderobdumper/426/obdumper-faq.png)

### 导数工具如何自定义日志打印级别？

您可以使用文本编辑器打开导数工具包中的 `{ob-loader-dumper}/conf/log4j2.xml` 文件。具体操作步骤：

将 Configuration > Loggers > name=`com.oceanbase.tools.loaddump` 的 Logger > 设置 level 为所需的日志打印级别。支持以下级别：DEBUG, INFO, WARN, ERROR。同时您可以在 Loggers 下更改其他组件的日志配置。

示例：将导数工具的日志打印级别设置为 DEBUG。

```xml
<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 日志？

1. 首先设置 JDBC 参数 log=true。
 2. 添加以下 Logger 至 Loggers：

   ```xml
   <logger additivity="false" level="trace" name="com.oceanbase.jdbc.internal.io">
     <AppenderRef ref="JdbcTraceAppender"/>
   </logger>

   ```
 3. 添加以下 Routing 至 Appenders。

   ```xml
   <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/obdumper`，查找关键字 `-Xms` 与 `-Xmx`，前者表示 JVM 初始化堆内存，后者表示 JVM 最大可申请的堆内存。

### 定时打印的性能监控日志里的指标分别是什么含义？

**Enqueue performance** 为生产端，即解析文件的性能指标； **Dequeue performance** 为消费端，即写入数据库的性能指标。更多详情请参见[OBDUMPER 工作原理](https://www.oceanbase.com/knowledge-base/obloader-obdumper-1000000000486923)。

其中，`1.sec.avg` 表示全局平均吞吐，`1.min.avg` 表示最近一分钟的平均吞吐。

## 数据处理常见问题

### 什么是 ETL？如何使用导数工具的 ETL 能力？

数据库 ETL 工具是用于将数据从一个数据库移动到另一个数据库的工具。ETL 代表提取（Extract）、转换（Transform）和加载（Load），表示从源数据库提取数据、将转换后的数据加载到目标数据库的过程。由于导数工具的工作场景并非在线迁移，因此导入时 “Extract” 的对象与导出时 “Load” 的对象，皆为文件系统或其他存储介质，而非源/目标数据库。“存储介质” 表示包括本地文件系统在内的多种存储系统，例如 Aliyun OSS，Amazon S3 和 HDFS。

导数工具同时通过丰富的[命令行选项](https://www.oceanbase.com/docs/common-oceanbase-dumper-loader-1000000000381203)与[控制文件](https://www.oceanbase.com/docs/common-oceanbase-dumper-loader-1000000000381211)来支持 “Transform” 能力。

### OBDUMPER 支持导出哪些结构定义？

Oracle 模式与 MySQL 模式下包括表、视图、函数等多种数据库对象的结构定义。需注意的是，在 OBServer 4.0.0 之前的版本，程序需显式提供 sys 租户的权限，例如 `--sys-user 'root'`, `'--sys-password' '******'`。当然，您也可以显式指定 `--no-sys` 选项，用于在限制模式下导出结构定义。

具体参考下表：

| 租户 | **提供 sys 租户的密码** | **未提供 sys 租户的密码** |
| --- | --- | --- |
| MySQL | 表, 视图, 表组, 存储过程, 函数 | 与 **提供 sys 租户的密码** 的导出行为基本相同，但是还存在以下遗留问题：   OceanBase 2.2.70之前的版本无法导出表组定义；   OceanBase 2.2.70之前的版本无法导出唯一索引的分区信息；   OceanBase Oracle 2.2.30及之前的版本无法导出索引定义；   OceanBase Oracle 2.2.70(含) ~ 4.0.0.0 版本无法导出分区表的唯一索引定义； |
| Oracle | 表, 视图, 触发器, 同义词, 序列, 存储过程, 函数, 包, 表组, 类型 | 同上 |

### OBDUMPER 导出数据时，为什么 `sec.avg` 和 `min.avg` 显示的导出速度相似？

`sec.avg` 表示全局的平均速度（秒级），`min.avg` 表示最近一分钟的平均速度（秒级）。

### 在控制台中输出日志时无响应，该如何解决？

可能是控制台输出被暂停或中止，导致日志输出被阻塞。解决方法：

1. 打开日志的配置文件 `{ob-loader-dumper}/conf/log4j2.xml`，查找如下配置：

   ```sql
   <Logger name="com.oceanbase.tools.loaddump" additivity="false" level="INFO">
   <AppenderRef ref="ConsoleAppender"/>
   <AppenderRef ref="InfoRoutingAppender"/>
   <AppenderRef ref="WarnRoutingAppender"/>
   <AppenderRef ref="ErrorRoutingAppender"/>
   </Logger>

   ```
 2. 删除 `<AppenderRef ref="ConsoleAppender"/>`，并尝试重新运行程序。

### CSV 与 CUT 格式有什么区别？

- CSV 格式具有以下特征：

     - 列分隔符须为单字符。
     - 大多数情况下存在定界符（即数据两边是否有引号）。
     - 大多数情况下包含 Header。
 - CUT 格式是一种类似 CSV 的较为灵活的格式，具有以下特征：

     - 列分隔符可以为单字符或者多字符。
     - 不存在定界符。
     - 不包含 Header。

### CSV 与 CUT 格式的列分隔符是特殊字符，该如何解决？

导数工具支持以 HEX 表示方式输入特殊字符。例如：`'\t'` 的 HEX 表示 `'0x09'`；`'Ctrl+O'`（'^O'）的 HEX 表示为 `'0x0F'`。

### 程序是否支持自定义查询导出？需要注意哪些问题？

使用 `--query-sql` 选项指定查询 SQL，适用于多表联查或复杂查询导出结果集的场景。使用该选项时，需要注意以下几点：

- 导出任务是单线程执行的。
 - 导出性能不作保证，您需要自行优化自定义 SQL 语句的查询性能。
 - 当仅在单表上使用条件查询时，可以使用以下替代方案有效提高性能：

     - 如需条件过滤，建议使用 `--where` 选项。
     - 如需数据转换，建议使用控制文件。

### OBDUMPER 中的 Block Size （--block-size）是指什么？

Block Size 指导出生成的最大文件尺寸，以 'MB' 或 'ROW' （行）为单位， 默认值 '1024MB'。当文件大小超过该值时，[程序会转而写入另一个文件](https://www.oceanbase.com/knowledge-base/obloader-obdumper-1000000000486923)，滚动号加 1。当该值为 0 时，代表不限制最大文件尺寸，但仍需注意文件系统或其他存储介质对最大文件尺寸的限制。例如，有些操作系统会限制文件大小（ext4 上文件不得超过 2TB）、OSS 追加上传的阈值是 5GB、OSS 与 S3 普通上传单个文件的尺寸阈值为 48.8 TB。

### 导出数据时，零值日期/零值时间（0000-00-00）导出为空值（NULL），如何保留其原始格式？

首先需要了解为什么零值时间导出后为空值。MySQL 允许零值日期，但 JDBC 无法正确获取零值，只能通过 JDBC 参数 `zeroDateTimeBehavior` 采取三种不同的处理方式：

- convertToNull：将日期转换成 NULL 值。即 **OBDUMPER 使用的默认值**，参见本篇文档中的**导数工具能否配置 OceanBase 会话变量**。
 - exception：抛出异常。
 - round：替换成最近的日期，即 0001-01-01。

对于一个设置了 NOT NULL 的列，程序可以区别空值和零值时间。例如，非空列值为 NULL 说明是零值日期。

而对于可空列，OBDUMPER 将无法分辨 NULL 与零值日期。例如，一个可空列中有可能存在 NULL 或者零值日期。所以，OBDUMPER 提供了一个参数 `--preserve-zero-datetime`，当指定该选项时，程序会统一将 NULL 转换为零值时间。

**涉及的 OceanBase MySQL 数据类型：DATE, DATETIME, TIMESTAMP。**

### 如何导出快照？是否支持导出某时间点/事务点的数据？闪回查询？

程序提供了以下几个选项：

- `--snapshot` 选项用于一致性导出，例如，仅导出 SSTable 的数据。
 - `--flashback-scn` 选项用于导出某事务点的数据。详见闪回查询。
 - `--flashback-timestamp` 选项用于导出某时间点的数据。详见闪回查询。

### 如何在备副本、备集群上导出？

导数工具 4.2.6 之前的版本，可以通过 `--weak-read` 在备副本导出，不支持在备集群导出。

导数工具 4.2.6 及之后的版本，可以自行配置 sql 会话变量 `ob_read_consistency`。 init_sql 语句：`SET ob_read_consistency = WEAK;`

### 当指定 --all 或 --table '*' 时，导数工具如何决定哪些表需要导出？

1. 程序会先从系统视图中查询出所有的表。

      - MySQL 租户下查询系统视图 information_schema.TABLES。
      - ORACLE 租户下查询系统视图 ALL_OBJECT。
 2. 根据黑白名单过滤。具体请参见本篇文档中的**如何选择性地导出某些表或某些列？是否支持黑白名单？**

### 如何选择性地导出某些表或某些列？是否支持黑白名单？

参考以下选项分类，需注意同类型的黑白名单不能混用。

- 白名单：`--table`，`--include-column-names`。
 - 黑名单：`--exclude-tables`, `--exclude-column-names`，`--exclude-data-types`。

### 如何控制程序的并发度？`--thread` 与 `--parallel` 有什么区别？

您可以通过 `--thread` 选项设置客户端并发度，`--parallel` 选项设置服务端并发度。

- 客户端并发度是指导数工具自身可以调用的线程数，默认情况下，`--thread` 的值为 CPU 逻辑核数 * 2。其作用范围包括但不限于：

     - 客户端连接池的大小。
     - 客户端模式下导出时，切分子任务时的并发度与同时处理的子任务数。
     - 服务端模式下导出时，同时处理的表数。
 - 服务端并发度是指 OBServer 在处理客户端请求时使用的并发度。事实上，`--parallel` 是一个直接透传给 OBServer 的参数。`--parallel` 默认值为 1。目前，其作用范围包括：

     - 服务端导出的总体并发（参考 SELECT INTO OUTFILE `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 语句。

### 如何编写控制文件？控制文件为什么不生效？

控制文件表示一个数据库表中的列与原始数据文件中的列之间的映射关系。有关控制文件与数据库表、原始数据文件之间的关系，请参见 [定义控制文件](https://www.oceanbase.com/docs/common-oceanbase-dumper-loader-1000000000381204)。

#### 场景一：控制文件中每一行与文件列一一对应

示例：使用 OBDUMPER 导出 `order` 表数据时，通过控制文件 `order.ctrl` 映射文件 `order.txt` 中表的列，控制文件中每一行与文件列一一对应。

![ctrl1](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/knowledge-base/obloaderobdumper/1300.obloader-operating-principle/1200.obloader-faq/ctrl%201.png)

控制文件中每一行都必须为存在的数据库表列名，而 `map` 函数中的参数为原始数据文件的列偏移量。例如控制文件 `order.ctrl` 中的 `id map(1)` 表示 `order.txt` 中的第 1 列对应 `order` 表中的 `id` 列。

控制文件中您可以不填写 `map` 关键字，此时默认的映射关系满足：**控制文件中自上而下，文件列自左到右，一一对应**。

上述示例仅为一种理想情况。在这种能够自上而下一一完美对应的条件下，您甚至无需声明控制文件。控制文件的作用旨在进行列筛选。

#### 场景二：表中包含自动递增列

示例：使用 OBDUMPER 导出包含 `id` 自增列的 `order` 表数据时，通过控制文件 `order.ctrl` 映射文件 `order.txt` 中表的列。

因 `id` 为自增列，文件 `order.txt` 中可能不会存在与 `id` 对应的列。此时，仅需要删除控制文件中对 `id` 的声明。

![ctrl2](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/knowledge-base/obloaderobdumper/1300.obloader-operating-principle/1200.obloader-faq/ctrl%202.png)

#### 场景三：修改表中多个列

示例：使用 OBDUMPER 导出 `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`。

![ctrl3](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/knowledge-base/obloaderobdumper/1300.obloader-operating-principle/1200.obloader-faq/ctrl%203.png)

### 预处理函数不生效？

预处理函数包含替换函数与生成函数，生成函数目前仅包括：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 关键字的使用。文件列是否能一一对应上数据库表列？
 - 列名大小写问题。OBDUMPER 4.2.0 之前的版本支持区分列名大小写，而 OBDUMPER 4.2.0 及之后的版本不支持区分。在数据库设置了大小写敏感的场景，需要在每个列名外加一层中括号，来表示“大小写敏感”。

## 错误处理常见问题

### 如何解决使用 OBDUMPER 导出时遇到 OOM 错误？

首先修改 bin/obdumper 脚本中的 JAVA 虚拟机内存参数。其次排除 OpenJDK GC Bug。

### 如何在调试模式下运行 OBDUMPER 排查问题？

直接运行 bin 目录下的调试脚本。  
 例如：obdumper-debug。

### 为表配置了控制文件，导出的数据为什么没有生效？

要求控制文件的名称与表名相同且大小写一致。MySQL 默认表名为小写，Oracle 默认表名为大写。

### OBDUMPER 导出数据时，为什么空表未产生空数据文件？

默认空表不会产生对应的空文件。`--retain-empty-files` 选项可保留空表所对应的空文件。

### OBDUMPER 运行脚本时，命令行参数未被正常解析的原因是什么？

可能是命令行参数中存在特殊符号。Linux 平台上运行 OBDUMPER，密码中存在大于号（> 是重定向符），导致运行的日志出现丢失。因此在不同的运行平台请使用正确的引号。

### OceanBase Oracle 模式下，使用 OBDUMPER 导出数据时，同一张表中的主键名和索引名相同导致导出重复数据。如何解决？

避免在同一张表中创建多个同名约束。如果表中已存在同名约束，可以删除唯一索引后重新创建一个不同名的唯一索引。具体请参见 [OceanBase 对象命名规范综述](https://www.oceanbase.com/docs/common-oceanbase-database-10000000001700668)。

### 报错信息太简短，如何获取更详细的错误堆栈？

您可以使用导数工具包中的 `obdumper-debug` 重新执行命令，最后的报错信息会包括完整的堆栈。如果您根据详细的错误信息仍无法解决问题，可以将其以文本形式或截图发送到阿里钉 “离线导数支持群” 以获取研发支持。

### 程序好像卡住了，应该如何解决？

首先，某些低版本的 JDK 有 GC 缺陷，会导致程序卡住。**推荐您使用 JDK 1.8.0_301 及之后的版本**。

其次，程序可能是执行某些步骤较为缓慢，并非卡住，您可以修改日志输出级别为 DEBUG 级别并重新运行程序来确认是否无响应（hang 住）。具体请参考本篇文档中的**导数工具如何自定义日志打印级别**。如果可以确定使用的 JDK 版本在推荐区间内，且程序确实无响应（hang 住），可以通过 jstack 工具采集 Java 进程的实时堆栈信息并寻求研发支持。

采集堆栈信息方法如下：

1. 通过执行命令 `jps -l` 列举出当前所有 Java 进程。
 2. 查询进程名包含 `Obloader` 或 `Obdumper` 的进程，记录其 pid。
 3. 执行命令 `jstack -l pid > jstack.log`。`jstack.log` 即为采集到的堆栈信息。

#### 注意

pid 必须为 Java 进程，而非导数工具包 bin 目录下的 shell 脚本。

### 程序为什么突然异常终止？日志未显示 “System exit 1”。

如果进程突然结束，极大概率是进程被系统关闭。请关注您的运行环境是否为虚拟容器。以 Docker 为例，Docker 会关闭资源占用率超标的容器进程，当出现此类情况时，请首先参考 [OBDUMPER 性能调优](https://www.oceanbase.com/docs/common-oceanbase-dumper-loader-1000000000381192)，合理降低进程的资源占用。

### 导出 CLOB 字段为空？

导数工具 4.2.7 之前的版本，由于 JDBC 的缺陷，导出较大的 CLOB 数据时（一般是 > 4mb）会出现此问题。解决方法：升级到 导数工具 4.2.7 及之后的版本。

### OBDUMPER 导出数据时报错：Unexpected end of stream、Connection is reset、Connection is closed。

此类报错表示服务端将连接中断了。您连接的服务端可能是 ODP 或 OBServer，也可能是 F5 或其他负载均衡中间件。解决方法：

首先，您可以通过监控、运维平台查看有无服务端的报警；如果无报警，则考虑查看服务端的日志。以 ODP 为例，查询与导数工具报错时间点吻合的 WARN 或 ERROR 日志，然后确认服务端断连的具体原因。如无日志，则可能是 ODP 由于某些故障发生了重启。

### OBDUMPER 导出数据时报错：Connection is timeout、Read timeout。

此类报错表示客户端等待服务端响应超时（Socket timeout）。Socket timeout 由 JDBC 参数 "socketTimeout" 控制，默认为 30 分钟。如何更改 JDBC 参数请参见本篇文档中的 **如何打开 jdbc-io 的 trace 日志**。解决方法：

首先，OBDUMPER 4.2.3 之前的版本存在缺陷，JDBC 参数 "socketTimeout" 默认为 10s。请考虑升级版本。

大多数情况下，服务端不会耗时 30 分钟处理请求。大概率是发生了丢包（服务端无回包或客户端未确认收包），请先提供 ODP 及 OBServer 在相关时间点的日志，并寻求研发人员支持。

### OBDUMPER 导出数据时报错：The system config `open_cursors` value may be not enough。

该报错表示 OBServer 系统参数 `open_cursors` 可能过小（一般小于导数工具默认的并发度，具体请参见本篇文档中的 **如何控制程序的并发度**。解决方法：

首先查询现有的 open_cursors 数量，并执行以下 SQL 调大 open_cursors：

```shell
alter system set `open_cursors`=？。

```

### OBDUMPER 导出数据时报错：java.lang.OutOfMemoryError: Java heap space。

该报错表示 JVM 堆内存超限。默认的 JVM 最大堆内存是 4GB，我们推荐您设置 JVM 内存为客户端机器可用内存的 60% 左右。解决方法：

通过编辑器打开 `{ob-loader-dumper}/bin/obdumper`，查找关键字 `-Xms` 与 `-Xmx`，前者代表 JVM 初始化堆内存，后者代表 JVM 最大可申请的堆内存。同时，考虑适当调低 `--thread` 从而降低并发度。如仍无法解决问题，请将工作目录下 jvm 自动导出的 '.hprof' 文件发给研发，并描述您的使用场景。

### OBDUMPER 导出数据时报错：Access denied for user 'root'。

如您 `-u` 指定的不为 root 用户，这是因为程序连接 OBServer 4.0.0 之前的版本时，需要 sys 租户信息。解决方法：请参见本篇文档中的**什么情况需要提供 sys 租户**。

### OBDUMPER 导出数据时报错：Unsupported feature or function。

如果使用的是 OBServer 2.2 之前的版本，这可能是因为程序在建立数据库连接时默认开启了 PS 协议。解决方法： 修改连接配置文件 `session.config.json`，设置 JDBC 参数 `useServerPrepStmt=false`。具体请参见本篇文档中的**导数工具能否配置 OceanBase 会话变量**。

### OBDUMPER 导出数据时报错：Table or view does not exist。

这可能是因为 `-u` 所指定的 user 缺少部分系统视图的查询权限。

解决方法：执行以下 SQL 语句，为用户赋予系统视图的查询权限。

```sql
grant select on `oceanbase`.* to user

```

### OBDUMPER 指定 `--query-sql` '大查询语句' 导出数据过程中报错：`Connection reset`。

登入 sys 租户，将 ODP 配置参数 `client_tcp_user_timeout` 和 `server_tcp_user_timeout` 设置为 0。

### OBDUMPER 启动报错：`Access denied for user 'root'@'xxx.xxx.xxx.xxx'`。

OBDUMPER 默认依赖 root@sys 用户和密码。如果集群中已为 root@sys 用户设置密码，请在命令行中输入 `--sys-password` 选项并指定正确的 root@sys 用户的密码。

### OBDUMPER 运行报错：`The target directory: "xxx" is not empty`。

为防止数据覆盖，导出数据前，OBDUMPER 会检查输出目录是否为空（`--skip-check-dir` 选项可跳过此检查）。

### OBDUMPER 运行报错：`Request to read too old versioned data`。

当前查询所依赖的数据版本已经被回收，用户需要根据查询设置 UNDO 的保留时间。
 例如：`set global undo_retention=xxx`（OceanBase V4.0.0-BP1 之前的版本）；`alter system set undo_retention=xxxx;`（OceanBase V4.0.0-BP1 之后的版本）。默认单位：秒。

### OBDUMPER 运行报错：`ChunkServer out of disk space`。

由于 `_temporary_file_io_area_size` 参数值过小引起存储块溢出错误，可修改该系统配置参数。
 例如：使用 `_temporary_file_io_area_size` 参数 `SELECT * FROM oceanbase.__all_virtual_sys_parameter_stat WHERE name='_temporary_file_io_area_size';` 查询该参数值，修改该参数值 `ALTER SYSTEM SET _temporary_file_io_area_size = 20;`。

### OBDUMPER 运行报错：`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` 语句。

### OBDUMPER 查询视图报错：`SELECT command denied to user 'xxx'@'%' for table SYS.XXX`。

由于用户无访问内部表或者视图的权限，需要运行语句 `GRANT SELECT SYS.XXX TO xxx;` 为用户进行授权。

### 导出结构时乱码；导出结构时指定 --file-encoding 不生效。

`--file-encoding` 用于指定导出的文件编码。默认是 UTF-8。

导出结构时 `--file-encoding` 不生效是导数工具 4.2.6 之前版本的已知缺陷，在导数工具 4.2.6 版本已经修复。

解决方法：升级版本至导数工具 4.2.6 及之后的版本。

## 性能调优常见问题

#### 说明

调优前，我们强烈推荐您先阅读 [OBDUMPER 工作原理](https://www.oceanbase.com/knowledge-base/obloader-obdumper-1000000000486923)。

### OBDUMPER 导出结构慢？

导出结构慢一般是查询系统表性能太差，您可以考虑适当提高并发度（`--thread`）。OBServer 4.0.0 之前的版本可以指定 `--no-sys` 来进行限制性导出，由于其会跳过部分系统视图的查询，所以有可能提升性能。有关限制性导出详情，请参见本篇文档中的 **OBDUMPER 支持导出哪些结构定义**。

如该问题仍无法解决，请通过 SQL 审计手段（sql_audit 或 OCP）获取 Top SQL，并寻求研发人员支持。

### OBDUMPER 导出数据慢？吞吐低？

首先，您可能需要了解导出的数据链路：

1. 首先导数工具会发送查询 SQL 到服务端。
 2. 服务端处理后，通过 JDBC 提供的接口返回数据。
 3. 导数工具将数据格式化后，进行落盘。

以上三个链路完全串行，任何一处慢都会导致总体吞吐不佳。所以建议先通过 SQL 审计工具确认查询性能并确认目的数据源 IO 的上限（如果为本地磁盘，查询磁盘 IO 上限；如果为其他存储类型，例如对象存储，请确认是否有限流）。

分几种情况讨论解决方法：

1. 请确认您的表结构是否支持工具充分利用并发性能。请参见 [OBDUMPER 工作原理](https://www.oceanbase.com/knowledge-base/obloader-obdumper-1000000000486923)。分区、键等结构都会影响整体的导出速率。如果源表为一张无主键且无分区的表，由于无法切分子任务，导数工具实际上在串行导出！与 `--thread` 等参数无关。
 2. 请确认客户端与服务端间的网络是否稳定、带宽和延迟的数据量。
 3. ORC 与 Parquet 为二进制列存格式，写入时需要压缩，大部分情况下落盘性能不如 CSV、 CUT 字符格式。
 4. 某些特殊情况的解决方法：

      - 导数工具 4.2.7 及之后的版本，可以启用并行写入。导数工具 4.2.7 及之后版本，程序将默认的并行写入行为改为了串行写入，但仍提供了并发写入的行为开关，这将使程序将每张表的数据分散写入到多个文件（具体请参考之前的行为），但将无法合并子文件。操作方式：

            - 通过任意文本编辑器打开文件：`<ob-loader-dumper>/bin/obdumper`。
            - 查找 Java 启动参数：`-Denable.parallel.write=false`。删除其注释，并将 `false` 改为 `true`。
      - 导数工具 4.2.7 之前的版本。

            - 如为 Oracle 租户，可能是因为 4.2.7 之前的版本的导数工具依赖的 JDBC 驱动仅支持[游标结果集](https://www.oceanbase.com/docs/common-oceanbase-connector-j-cn-1000000000271789)。导数工具 4.2.7 及之后版本依赖的 JDBC 支持启用流式结果集，可以有效地提升导出性能。

上一篇

[OBDUMPER 支持导出的文件格式](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000486924)

下一篇

[OBDUMPER 服务端模式备份遇到报错 ERROR 4009: IO error 的原因及解决方法](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000002829038) ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
