PostgreSQL异常:An I/O error occurred while sending to the backend

打印 上一主题 下一主题

主题 1399|帖子 1399|积分 4197


在使用PostgreSQL数据库批量写入数据的时候,遇到了一个问题,异常内容如下:
  1. Cause: org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
复制代码
报错内容

报错提示1

  1. Caused by: org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
  2.         at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:336)
  3.         at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:446)
  4.         at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:370)
  5.         at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:149)
  6.         at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:138)
复制代码
报错提示2

  1. Caused by: java.io.IOException: Tried to send an out-of-range integer as a 2-byte value: 1847252
  2.         at org.postgresql.core.PGStream.sendInteger2(PGStream.java:252)
  3.         at org.postgresql.core.v3.QueryExecutorImpl.sendParse(QueryExecutorImpl.java:1470)
  4.         at org.postgresql.core.v3.QueryExecutorImpl.sendOneQuery(QueryExecutorImpl.java:1793)
  5.         at org.postgresql.core.v3.QueryExecutorImpl.sendQuery(QueryExecutorImpl.java:1356)
  6.         at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:301)
  7.         ... 117 common frames omitted
复制代码
问题分析

从首个错误信息中可以看出,在PostgreSQL运行SQL语句时遭遇了输入/输出(I/O)异常,这意味着所执行的SQL语句存在某种问题或数据库文件体系有潜在故障。
而第二条错误信息则展现,PostgreSQL在向客户端传输数据时,数据量凌驾了预设的限定。这通常表明,执行中的SQL查询结果过于庞大,超出了体系默认的传输容量,大概是由于查询返回了过多的数据行或单行数据包含大量信息所致。
查察源码

  1.   /**
  2.    * Sends a 2-byte integer (short) to the back end.
  3.    *
  4.    * @param val the integer to be sent
  5.    * @throws IOException if an I/O error occurs or {@code val} cannot be encoded in 2 bytes
  6.    */
  7.   public void sendInteger2(int val) throws IOException {
  8.     if (val < Short.MIN_VALUE || val > Short.MAX_VALUE) {
  9.       throw new IOException("Tried to send an out-of-range integer as a 2-byte value: " + val);
  10.     }
  11.     int2Buf[0] = (byte) (val >>> 8);
  12.     int2Buf[1] = (byte) val;
  13.     pgOutput.write(int2Buf);
  14.   }
复制代码
sendInteger2方法的作用是将一个整型值转换成短整型的二进制表示,并通过输出流发送给后端。假如输入的值超出短整型的范围,大概在写入过程中出现I/O错误,则会抛出IOException。
在方法内部,起首举行了一次范围检查,确保传入的整数值在短整型(short)的表树模围内,即介于 Short.MIN_VALUE 和 Short.MAX_VALUE 之间。假如超出范围,会抛出一个 IOException,指明试图发送的值过大或过小,无法用两个字节表示。
上面的错误提示,能确定就是在这块抛出的了,接下来重点查察代码中批量写入数据的代码。
问题发现

拿到接口执行的SQL以后,发现是一个批量写入的SQL,执行语句特别长,在Navicat中执行就直接报错了;修改批量写入的数据条数,发现是可以正常执行的;
伪代码如下:
  1. // 从一个响应中获取一个名为"list"的数据集合
  2. List<CustomEntity> entityList = ExtractListFromResponse(response, "list");
  3. // 使用一个数据访问层组件,将数据插入到数据库中的指定表中
  4. DataMapper.persistResponseData(entityList, targetTableName);
复制代码
问题解决

将大聚集举行拆分

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

   请确保自己的项目当中使用了MybatisPlus
  1. // 从一个响应中获取一个名为"list"的数据集合
  2. List<CustomEntity> entityList = ExtractListFromResponse(response, "list");
  3. // 使用MybatisPlus的批量写入,指定每批写入条数
  4. customService.saveBatch(entityList,1000);
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

小小小幸运

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表