应优先使用流式读取避免oom:blob用getbinarystream()配bufferedinputstream逐块读,text类用getcharacterstream()按字符/行解析,禁用getbytes()和getstring()等全量加载方法。

Java 中处理 ResultSet 的大数据字段(如 MySQL 的 BLOB 和 TEXT),关键在于避免一次性加载全部内容到内存,防止 OOM;应优先使用流式读取 + 按需处理的方式。
用 getBinaryStream() / getAsciiStream() / getCharacterStream() 替代 getBytes() / getString()
对 BLOB、CLOB、TEXT 类型字段,不要调用 getBlob().getBytes() 或 getString() —— 这会把整个二进制或文本内容加载进内存。应改用流接口:
-
BLOB:用
rs.getBinaryStream("column_name")获取InputStream,配合BufferedInputStream逐块读取 -
TEXT / LONGTEXT:用
rs.getCharacterStream("column_name")获取Reader,适合按字符/行解析(如 JSON、XML、日志) - MEDIUMTEXT / TINYTEXT 若确定体积小(getString(),但需评估风险
设置合适的 fetchSize 和禁用 auto-commit(尤其写入场景)
从 ResultSet 读取大字段时,JDBC 驱动默认可能缓存整行数据。需主动优化:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 执行查询前设置
statement.setFetchSize(Integer.MIN_VALUE)(MySQL Connector/J 支持流式游标,等效于“逐行获取”) - 确保连接未启用 auto-commit(
connection.setAutoCommit(false)),避免驱动为事务安全而缓存结果集 - MySQL 中还需在 URL 加参数:
?useServerPrepStmts=false&cachePrepStmts=false&tinyInt1isBit=false(部分版本影响流式读取)
写入大字段时用 setBinaryStream() / setCharacterStream()
向 BLOB/TEXT 插入或更新大数据,同样避免先构造 byte[] 或 String:
-
BLOB:用
ps.setBinaryStream(1, inputStream, length),length 可传 -1(表示未知长度,驱动自动探测) -
TEXT:用
ps.setCharacterStream(1, reader, length),reader 可来自文件、StringReader 或网络流 - 注意:MySQL 的
max_allowed_packet需大于待写入数据,否则报错 “Packet too large”
注意 MySQL 驱动版本与 LOB 流行为差异
不同 Connector/J 版本对流式读取支持不同:
- 8.0+ 默认启用流式结果(需配合
setFetchSize(Integer.MIN_VALUE)) - 5.1.x 需显式加 URL 参数:
&useCursorFetch=true&defaultFetchSize=1 - 调用
getBinaryStream()后,该列不能再调用其他 getter(如getString()),否则抛异常 - 流使用完务必关闭(try-with-resources),否则连接可能被 hold 住
不复杂但容易忽略:流式读取不是银弹,要结合业务场景——比如导出文件就直接写磁盘,做内容分析就边读边解析,别全 load 进内存。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










