# [FAQ] MyBatis 框架 cursorfetch 如何配置避免全表扫描导致 TiDB OOM

## Key Words

MyBatis, Java, Fetchsize, cursorfetch

## Description

MyBatis 是目前比较流行的 Java 数据访问框架，主要用于管理 SQL并完成结果集和 Java 对象的来回映射工作。FetchSize 设置 Integer.MIN_VALUES 和 使用 Cursor Fetch 实际在 TiDB Sever 处理方式区别是什么？

### 使用 StreamingResult 流式获取执行结果

```text
官方文档原文：使用 StreamingResult 流式获取执行结果
一般情况下，为提升执行效率，JDBC 会默认提前获取查询结果并将其保存在客户端内存中。但在查询返回超大结果集的场景中，客户端会希望数据库服务器减少向客户端一次返回的记录数，等客户端在有限内存处理完一部分后再去向服务器要下一批。
 
在 JDBC 中通常有以下两种处理方式：
 
方案一：设置 FetchSize 为 Integer.MIN_VALUE 让客户端不缓存，客户端通过 StreamingResult 的方式从网络连接上流式读取执行结果。
 
使用流式读取数据时，需要将 resultset 读取完成或 close 后，才能继续使用该语句进行下次查询，否则会报错 No statements may be issued when any streaming result sets are open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries.。
 
方案二：如果需要在 resultset 读取完成或 close 前进行查询避免上述报错，可在 URL 中添加配置参数 clobberStreamingResults=true，这样会自动 close resultset，但之前流式查询未被读取的结果集会丢失。
 
使用 Cursor Fetch，首先需设置 FetchSize 为正整数，且在 JDBC URL 中配置 useCursorFetch = true。
 
TiDB 中同时支持两种方式，但更推荐使用第一种将 FetchSize 设置为 Integer.MIN_VALUE 的方式，比第二种功能实现更简单且执行效率更高。
```

## Content

推荐使用 FetchSize 设置为 Integer.MIN_VALUES 方式，并且设置 clobberStreamingResults=true 确保不会出现预期报错，导致不可持续执行。如果使用 Cursor Fetch 时候，实际 TiDB 会将一次把所有的 Next 调用完，存储到 TiDB Sever，再由 ByBatis 的 Cursor 按照设置的 Integer.MIN_VALUE 批次取值，所以如果是大表情况会导致 TiDB Sever OOM。如果是使用 Stream 模式，Client 会分批次向 TiDB Sever 请求数据，执行多次 Next 吐数据给他。

## Affected Versions

All of version