PostgreSQL的SQL语句参数上限 An I/O error occurred while sending to the backend

事故现场:

数据库我用postgreSQL,持久成框架mybatis
现在有一个操作,需要将一大批数据(3000+)插入数据库,后台直接报错,报错原因如下:

org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.

Caused by: java.io.IOException: Tried to send an out-of-range integer as a 2-byte value: 50805

原因:批量插入的顶峰在JDBC-Driver出现天花板.
简单来说就是SQL语句参数上限

可能我们首先想到的解决办法是分段批量插入,将sql语句分成几次执行,比如现在有3500条数据,一次性最多插入1500,分为3次插入;那代码怎么实现呢?
下面介绍2种解决方法,2种方法都用了递归算法;(当时的情况我这边一次性可以插入1800条,具体要看数据表中有多少字段)

  • 注:以下方法可以写在service的通用方法中(如果有的话),这样所有实体类的service都可以调用

第一种方法:

这是我的第一次尝试,虽然不太灵活,但能用,记录一下;后来才有第二种方法;

直接用java.util.List包提供的方法subList(int fromIndex, int toIndex);
subList是List接口中定义的一个方法,该方法主要用于返回一个集合中的一段,可以理解为截取一个集合中的部分元素,他的返回值也是一个List。方法中的2个参数可以看成是数组的下标;代码如下:

/**
 * 递归插入
 * @author: fangzf
 * @param:  @param all     需要批量插入的集合
 * @param:  @param strart  开始的下标
 * @param:  @param end     结束的下标(包头不包尾)
*/
public void add (List<T> all,int strart, int end){

    if(all.size()<=end){
        end = all.size();
    }

    //截取strart ~ end条数据
    List<T> collect = all.subList(strart, end);
    if(CollUtil.isEmpty(collect)){
        return;
    }

     //批量插入数据的方法(这里是通用的批量插入数据方法)
    insertList(collect);
     //递归 每次插入1500条数据,这里1500写死了,就是不灵活的地方
     //可以再传一个参数过来,这样会比较灵活
    add(all,strart+1500,end+1500);
}

//调用批量插入的方法 all表示业务中要插入的数据数组
add(all,0,1500);
关于subList方法需要谨慎使用

在《阿里巴巴Java开发手册》中有提到subList方法需要谨慎使用,具体可以看一下这篇文章:
为什么阿里巴巴要求谨慎使用ArrayList中的subList方法:http://www.matools.com/blog/190706621

第二种方法:(推荐)

说到数组的操作我们肯定会想起java8提供强大的lambda表达式(链接到lambda表示文章),这里要用到skip和limit方法;

  • skip(n):跳过元素,返回一个扔掉前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。

  • limit(n):截断流,使其元素不超过给定数量。

代码如下:

//递归插入
public void add (List<Dormitory> all,long strart,long limit){
    //截取 从strart开始截取 截取limit条
	List<Dormitory> collect = all.stream().skip(strart).limit(limit).collect(Collectors.toList());
	if(CollUtil.isEmpty(collect)){
         return;
	}
      //批量插入数据的方法
	insertList(collect);
     //递归 每次插入limit条数据
	add(all,strart+limit,limit);
}

//调用批量插入的方法 all表示业务中要插入的数据数组
add(all,0L,1500L);

简单强大,推荐

  • 9
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
当出现 "An I/O error occurred while sending to the backend" 的异常时,这通常意味着客户端与 PostgreSQL 服务器之间的连接已经断开或无法建立,或者在通信过程中出现了网络故障。解决此异常的方法如下: 1. 检查网络连接:首先需要确认网络连接是否正常。可以尝试 ping PostgreSQL 服务器,看看是否能够正常连接。如果网络连接出现问题,需要解决网络问题。 2. 检查 PostgreSQL 服务器状态:检查 PostgreSQL 服务器是否正常运行,并且能够接受新的连接请求。可以尝试使用 psql 工具或其他客户端工具连接 PostgreSQL 服务器,看看是否能够成功连接。 3. 检查 PostgreSQL 服务器日志:如果 PostgreSQL 服务器无法处理客户端请求,可能会在日志中记录错误信息。可以检查 PostgreSQL 服务器的日志文件,找到相关的错误信息,从而确定出错的原因。 4. 调整客户端连接参数:如果客户端连接参数设置不当,可能会导致连接断开。可以尝试调整客户端连接参数,比如增加连接超时时间、调整缓冲区大小等。 5. 升级 PostgreSQL 版本:如果出现此异常的原因是 PostgreSQL 的 bug,可以尝试升级到最新版本,以获得更好的稳定性和更好的性能。 总之,解决 "An I/O error occurred while sending to the backend" 的异常需要结合具体情况进行分析和解决,可以根据异常信息以及上述方法进行排查。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值