You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

设置大fetchSize查询Oracle触发ArrayIndexOutOfBoundsException求助

问题描述

使用JDBC查询Oracle数据库时,设置fetchSize为10执行正常,但设置为100000时抛出ArrayIndexOutOfBoundsException,错误栈指向Oracle驱动的T4CNumberAccessor.unmarshalOneRow方法。相关代码如下:

ParsedSql parsedSql = NamedParameterUtils.parseSqlStatement(apiSql);
MapSqlParameterSource paramSource = new MapSqlParameterSource(param);
String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
List<SqlParameter> declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource);
PreparedStatementCreatorFactory creatorFactory = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters);
Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null);
PreparedStatementCreator creator = creatorFactory.newPreparedStatementCreator(params);
PreparedStatement preparedStatement = creator.createPreparedStatement(conn);

if(batchCount > maxBatchCount || batchCount == 0){
    batchCount = (int)maxBatchCount;
}
preparedStatement.setFetchSize(batchCount);
ResultSet resultSet = preparedStatement.executeQuery();

错误信息:

java.sql.SQLException: Error
at com.alibaba.druid.pool.DruidDataSource.handleConnectionException(DruidDataSource.java:1770)
at com.alibaba.druid.pool.DruidPooledConnection.handleException(DruidPooledConnection.java:133)
at com.alibaba.druid.pool.DruidPooledStatement.checkException(DruidPooledStatement.java:82)
at com.alibaba.druid.pool.DruidPooledPreparedStatement.executeQuery(DruidPooledPreparedStatement.java:240)
...
Caused by: java.lang.ArrayIndexOutOfBoundsException: 802200000
at oracle.jdbc.driver.T4CNumberAccessor.unmarshalOneRow(T4CNumberAccessor.java:201)
at oracle.jdbc.driver.T4CTTIrxd.unmarshal(T4CTTIrxd.java:945)
...

环境信息:

  • JDK 8
  • ojdbc-11.2.0.4
  • Oracle 10/11/12
  • 执行的是包含89个字段的全量查询SQL
原因分析

这个错误是Oracle JDBC驱动内部的缓冲区计算缺陷导致的:

  • 当fetchSize设置过大(如100000),同时查询结果包含大量字段(89个)时,驱动为数值类型字段分配解析缓冲区时,计算的数组大小超出了内部限制,触发数组越界。
  • ojdbc-11.2.0.4属于较老版本,针对大fetchSize+多字段的场景存在未修复的bug,尤其是在处理NUMBER类型字段的批量解析时。
解决方案
  1. 降低fetchSize到合理范围
    不要设置过大的fetchSize,建议调整为1000-5000之间。过大的fetchSize不仅会触发驱动bug,还会占用大量内存、增加GC压力,反而降低整体性能。

  2. 升级JDBC驱动版本
    更换为适配JDK8的更高版本驱动,比如ojdbc8(兼容Oracle 10/11/12)或12.2.0.1及以上的ojdbc版本。新版本驱动修复了大量缓冲区计算和数据解析的问题,能更好地处理大fetchSize场景。

  3. 检查并优化字段类型
    如果查询结果中存在高精度NUMBER类型字段(如NUMBER(38)),在业务允许的前提下,可以调整字段精度,或者在查询时显式转换为合适的类型,减少驱动解析时的缓冲区压力。

  4. 分页替代全量查询
    即使需要获取全量数据,也可以通过分页查询分批处理,比如使用Oracle的ROWNUM或FETCH NEXT ... ROWS ONLY语法,分批次读取数据,避免一次性设置过大的fetchSize。

内容的提问来源于stack exchange,提问作者Ivan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 11:30:56