---
title: OceanBase 数据库开启 NLJ BATCH 优化在 BATCH RESCAN 和 UNION 算子正交导致的执行报错 4016-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于 OceanBase 数据库开启 NLJ BATCH 优化在 BATCH RESCAN 和 UNION 算子正交导致的执行报错 4016相关的常见问题和使用技巧，帮助您快速解决 OceanBase 数据库开启 NLJ BATCH 优化在 BATCH RESCAN 和 UNION 算子正交导致的执行报错 4016的难题。
---
切换语言

- 简体中文
- English

划线反馈

# OceanBase 数据库开启 NLJ BATCH 优化在 BATCH RESCAN 和 UNION 算子正交导致的执行报错 4016

更新时间：2026-05-15 09:06

适用版本： V4.1.x、V4.2.x 内容类型：Troubleshoot  

## 问题现象

在存在问题的 OceanBase 数据库版本中，当开启 `SET GLOBAL _NLJ_BATCHING_ENABLED =true` 同时用户的计划中存在 NESTED-LOOP JOIN 算子和 UNION ALL 正交相关，在执行时可能会报错 `ERROR 4016 (HY000): Internal error`。

示例如下。

1. 创建表。

   ```shell
   obclient [mysql]> CREATE TABLE t1(a int primary key, b int);
   Query OK, 0 rows affected (0.330 sec)

   ```

   ```shell
   obclient [mysql]> CREATE TABLE t2(a int primary key, b int);
   Query OK, 0 rows affected (0.389 sec)

   ```

   ```shell
   obclient [mysql]> CREATE TABLE t3(a int primary key, b int);
   Query OK, 0 rows affected (0.317 sec)

   ```
 2. 插入数据。

   ```shell
   obclient [mysql]> SET @rownum=0;
   ERT INTO t1 SELECT @rownum:=@rownum+1, @rownum FROM TABLE(generator(2000)) t;Query OK, 0 rows affected (0.007 sec)

   ```

   ```shell
   obclient [mysql]> INSERT INTO t1 SELECT @rownum:=@rownum+1, @rownum FROM TABLE(generator(2000)) t;
   Query OK, 2000 rows affected (0.291 sec)
   Records: 2000  Duplicates: 0  Warnings: 0

   ```

   ```shell
   obclient [mysql]> SET @rownum=0;
   INTO t2 SELECT @rownum:=@rownum+1, @rownum FROM TABLE(generator(2000)) t;Query OK, 0 rows affected (0.005 sec)

   ```

   ```shell
   obclient [mysql]> INSERT INTO t2 SELECT @rownum:=@rownum+1, @rownum FROM TABLE(generator(2000)) t;
   Query OK, 2000 rows affected (0.265 sec)
   Records: 2000  Duplicates: 0  Warnings: 0

   ```

   ```shell
   obclient [mysql]> SET @rownum=0;
   ERT INTO t3 SELECT @rownum:=@rownum+1, @rownum FROM TABLE(generator(2000)) t;Query OK, 0 rows affected (0.003 sec)

   ```

   ```shell
   obclient [mysql]> INSERT INTO t3 SELECT @rownum:=@rownum+1, @rownum FROM TABLE(generator(2000)) t;
   Query OK, 2000 rows affected (0.308 sec)
   Records: 2000  Duplicates: 0  Warnings: 0

   ```
 3. 执行如下 SQL 语句。

   ```shell
   obclient [mysql]> SELECT /*+use_nl(t1, t)*/ COUNT(1) FROM t1, (SELECT a FROM t2 UNION ALL SELECT a FROM t3) t WHERE t1.b>0 AND t1.a=t.a;
   ERROR 4016 (HY000): Internal error

   ```
 4. 展示 SQL 语句执行计划。

   ```shell
   obclient [mysql]> EXPLAIN SELECT /*+use_nl(t1, t)*/ COUNT(1) FROM t1, (SELECT a FROM t2 UNION ALL SELECT a FROM t3) t WHERE t1.b>0 AND t1.a=t.a;

   ```

   输出结果如下。

   ```shell
   +------------------------------------------------------------------------------------+
   | Query Plan                                                                         |
   +------------------------------------------------------------------------------------+
   | =============================================================                      |
   | |ID|OPERATOR                     |NAME|EST.ROWS|EST.TIME(us)|                      |
   | -------------------------------------------------------------                      |
   | |0 |SCALAR GROUP BY              |    |1       |8301        |                      |
   | |1 |└─NESTED-LOOP JOIN           |    |200     |8297        |                      |
   | |2 |  ├─TABLE FULL SCAN          |t1  |200     |110         |                      |
   | |3 |  └─SUBPLAN SCAN             |t   |2       |41          |                      |
   | |4 |    └─UNION ALL              |    |2       |41          |                      |
   | |5 |      ├─DISTRIBUTED TABLE GET|t2  |1       |21          |                      |
   | |6 |      └─DISTRIBUTED TABLE GET|t3  |1       |21          |                      |
   | =============================================================                      |
   | Outputs & filters:                                                                 |
   | -------------------------------------                                              |
   |   0 - output([T_FUN_COUNT(*)]), filter(nil), rowset=256                            |
   |       group(nil), agg_func([T_FUN_COUNT(*)])                                       |
   |   1 - output(nil), filter(nil), rowset=256                                         |
   |       conds(nil), nl_params_([t1.a(:0)]), use_batch=true                           |
   |   2 - output([t1.a]), filter([t1.b > 0]), rowset=256                               |
   |       access([t1.a], [t1.b]), partitions(p0)                                       |
   |       is_index_back=false, is_global_index=false, filter_before_indexback[false],  |
   |       range_key([t1.a]), range(MIN ; MAX)always true                               |
   |   3 - output(nil), filter(nil), rowset=256                                         |
   |       access(nil)                                                                  |
   |   4 - output([UNION([1])]), filter(nil), rowset=256                                |
   |   5 - output([t2.a]), filter(nil), rowset=256                                      |
   |       access([GROUP_ID], [t2.a]), partitions(p0)                                   |
   |       is_index_back=false, is_global_index=false,                                  |
   |       range_key([t2.a]), range(MIN ; MAX)always true,                              |
   |       range_cond([:0 = t2.a])                                                      |
   |   6 - output([t3.a]), filter(nil), rowset=256                                      |
   |       access([GROUP_ID], [t3.a]), partitions(p0)                                   |
   |       is_index_back=false, is_global_index=false,                                  |
   |       range_key([t3.a]), range(MIN ; MAX)always true,                              |
   |       range_cond([:0 = t3.a])                                                      |
   +------------------------------------------------------------------------------------+
   34 rows in set (0.116 sec)

   ```

## 问题诊断

### 事前巡检

- 计划中存在 NESTED-LOOP JOIN 算子和 UNION ALL / UNION 算子。

  ![hiy89i-yi6780-hj8i8i-jio89](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/knowledge-base/database/sql/202311274016problem.png)

### 事后诊断

```shell
WDIAG [SQL.ENG] batch_fill_group_buffer (ob_group_join_buffer.cpp:650) [802752][T1032_L0_G0][T1032][xxxxx-xxxxx-xxxxx-xxxxx] [lt=6][errcode=-4016] rescan right failed(ret=-4016, ret="OB_ERR_UNEXPECTED")
WDIAG [SQL.ENG] group_get_left_batch (ob_nested_loop_join_op.cpp:766) [802752][T1032_L0_G0][T1032][xxxxx-xxxxx-xxxxx-xxxxx] [lt=7][errcode=-4016] batch fill group buffer failed(ret=-4016, ret="OB_ERR_UNEXPECTED")
WDIAG [SQL.ENG] get_left_batch (ob_nested_loop_join_op.cpp:616) [802752][T1032_L0_G0][T1032][xxxxx-xxxxx-xxxxx-xxxxx] [lt=6][errcode=-4016] fail to get left batch(ret=-4016)

```

1. 通过日志关键词 `grep 'rescan right failed' observer.log`。
 2. 找到报错的日志 `rescan right failed` 同行的 trace_id。
 3. `grep 'trace_id'` 如果日志与给出参照连续 3 条日志相同侧可以判断为相同问题。

## 问题原因

OceanBase 数据库实现逻辑中 NESTED-LOOP JOIN 执行优化的思路是减少执行过程中对数据的访问次数，因此需要使用到 BATCH RESCAN 的执行方式。和基础 NESTED-LOOP JOIN 算法不同，BATCH RESCAN 将驱动表的多次 RESCAN 操作合并成一次执行，BATCH RESCAN 要求参数带一个 Array 的标记。UNION 算子有两个 TABLE SCAN 子算子，由于一个实现的问题，第一个 TABLE SCAN 算子在第一批的时候污染了参数的标记。导致第二个 TABLE SCAN 拿到非法的参数，多个算子共用同一个参数的情况下，如果第一个算子切换后参数没有恢复，会影响后续共享该参数的算子的正常执行。所以有了非预期的 4016 报错。

## 问题的风险及影响

执行 SQL 报错 `ERROR 4016 (HY000): Internal error` 执行异常。

## 影响的版本

OceanBase 数据库 V4.2.1 GA Hotfix1 及之前版本，V4.1.0 BP4 Hotfix1 及之前版本。

## 解决方法

升级至问题已修复版本。目前已修复的版本包括 OceanBase 数据库 V4.2.1 GA Hotfix2 (oceanbase-4.2.1.0-100020042023102310) 及之后版本。

## 规避方式

关闭 NLJ BATCH 优化。

```shell
obclient > SET GLOBAL _NLJ_BATCHING_ENABLED = false;

```

#### 注意

关闭 NLJ BATCH 优化会存在性能回退。

Previous

[包含 NLJ 的 SQL 由于优化器默认选择条件下压计划而选择了错误的索引，生成不优计划](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000006405841)

Next

[SQL 执行报错 -4119，RPC packet to send too long](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000000210005) ![有帮助](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) 咨询热线
