PostgreSQL异常:An IO error occurred while sending to the backend

在使用PostgreSQL数据库批量写入数据的时候,遇到了一个问题,异常内容如下:

复制代码
Cause: org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
报错内容
报错提示1
复制代码
Caused by: org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:336)
	at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:446)
	at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:370)
	at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:149)
	at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:138)
报错提示2
复制代码
Caused by: java.io.IOException: Tried to send an out-of-range integer as a 2-byte value: 1847252
	at org.postgresql.core.PGStream.sendInteger2(PGStream.java:252)
	at org.postgresql.core.v3.QueryExecutorImpl.sendParse(QueryExecutorImpl.java:1470)
	at org.postgresql.core.v3.QueryExecutorImpl.sendOneQuery(QueryExecutorImpl.java:1793)
	at org.postgresql.core.v3.QueryExecutorImpl.sendQuery(QueryExecutorImpl.java:1356)
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:301)
	... 117 common frames omitted
问题分析

从首个错误信息中可以看出,在PostgreSQL运行SQL语句时遭遇了输入/输出(I/O)异常,这意味着所执行的SQL语句存在某种问题或数据库文件系统有潜在故障。

而第二条错误信息则揭示,PostgreSQL在向客户端传输数据时,数据量超过了预设的限制。这通常表明,执行中的SQL查询结果过于庞大,超出了系统默认的传输容量,可能是因为查询返回了过多的数据行或单行数据包含大量信息所致。

查看源码
复制代码
  /**
   * Sends a 2-byte integer (short) to the back end.
   *
   * @param val the integer to be sent
   * @throws IOException if an I/O error occurs or {@code val} cannot be encoded in 2 bytes
   */
  public void sendInteger2(int val) throws IOException {
    if (val < Short.MIN_VALUE || val > Short.MAX_VALUE) {
      throw new IOException("Tried to send an out-of-range integer as a 2-byte value: " + val);
    }

    int2Buf[0] = (byte) (val >>> 8);
    int2Buf[1] = (byte) val;
    pgOutput.write(int2Buf);
  }

sendInteger2方法的作用是将一个整型值转换成短整型的二进制表示,并通过输出流发送给后端。如果输入的值超出短整型的范围,或者在写入过程中出现I/O错误,则会抛出IOException。

在方法内部,首先进行了一次范围检查,确保传入的整数值在短整型(short)的表示范围内,即介于 Short.MIN_VALUE 和 Short.MAX_VALUE 之间。如果超出范围,会抛出一个 IOException,指明试图发送的值过大或过小,无法用两个字节表示。

上面的错误提示,能确定就是在这块抛出的了,接下来重点查看代码中批量写入数据的代码。

问题发现

拿到接口执行的SQL以后,发现是一个批量写入的SQL,执行语句特别长,在Navicat中执行就直接报错了;修改批量写入的数据条数,发现是可以正常执行的;

伪代码如下:

复制代码
// 从一个响应中获取一个名为"list"的数据集合
List<CustomEntity> entityList = ExtractListFromResponse(response, "list");

// 使用一个数据访问层组件,将数据插入到数据库中的指定表中
DataMapper.persistResponseData(entityList, targetTableName);
问题解决
将大集合进行拆分
复制代码
// 使用org.apache.commons.collections4提供的ListUtils工具类,将大集合按照每组1000条进行拆分
List<List<CustomEntity>> partition = ListUtils.partition(entityList,1000);
// 循环遍历拆分之后的集合,分批写入数据
for (List<CustomEntity> customEntityList : partition){
    // 使用一个数据访问层组件,将数据插入到数据库中的指定表中
    DataMapper.persistResponseData(customEntityList, targetTableName);
}
使用MybatisPlus的批量写入

请确保自己的项目当中使用了MybatisPlus

复制代码
// 从一个响应中获取一个名为"list"的数据集合
List<CustomEntity> entityList = ExtractListFromResponse(response, "list");
// 使用MybatisPlus的批量写入,指定每批写入条数
customService.saveBatch(entityList,1000);
相关推荐
YH_Analytics13 小时前
2026 高压 E-House 市场深度分析报告市场格局
网络·数据库
后台模板学习13 小时前
MongoDB 与 MySQL 在 IM 即时聊天场景中该
数据库·mysql·mongodb
KaiwuDB13 小时前
企业级数据库数据保护:KaiwuDB KaiwuDB V3.3.0 发布:S3 冷热分层存储与主备集群能力增强实战解析模场景备份恢复方案解析
数据库·时序数据库·kaiwudb·发版·多模时序数据库·冷热分层存储·主备集群
DataY14 小时前
MySQL CDC 直接写进 Doris 汇总模型:同步即汇总,明细不用搬两遍
数据库
琳达爱分享14 小时前
客服改了地址,发货任务把它改了回去:一次没人报错的覆盖
数据库
IT大白鼠14 小时前
渗透测试实战从靶场搭建到渗透流程——第 8 篇 · 服务型靶标(上):MySQL 双版本写文件链
数据库·mysql·渗透测试
piaoyiren14 小时前
Python FTP 服务端项目详细功能文档
网络·数据库·python
少年的范儿14 小时前
Windows 安装 MySQL 8.4 教程(ZIP 解压版):配置 my.ini、初始化数据库与启动服务
数据库·windows·mysql
l1t14 小时前
DeepSeek总结的AI 智能体应该用哪种语言搜索其记忆:SQL 还是 SPARQL?
数据库·人工智能·sql
麦壳饼15 小时前
SonnetDB:PID 调参实战:阶跃响应分析与参数解读
数据库·sonnetdb