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

最近在跟踪项目的时候,发现了一个bug:

[2023-11-27 15:10:45.311] [http-nio-48081-exec-7]  WARN  com.zaxxer.hikari.pool.ProxyConnection checkException 182 - telecom_total - Connection org.postgresql.jdbc.PgConnection@1b0e03c6 marked as broken because of SQLSTATE(08006), ErrorCode(0)
org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:338)
	at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:447)
	at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:368)
	at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:159)
	at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:148)
	at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
	at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.execute(HikariProxyPreparedStatement.java)
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:64)
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)
	at sun.reflect.GeneratedMethodAccessor126.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:64)
	at com.sun.proxy.$Proxy345.query(Unknown Source)
	at sun.reflect.GeneratedMethodAccessor126.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:64)
	at com.sun.proxy.$Proxy345.query(Unknown Source)
	at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63)
	at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:325)
	at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109)
	at sun.reflect.GeneratedMethodAccessor206.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:49)
	at com.cqcdi.zcldgl.system.config.mybatis.interceptor.MybatisQueryInterceptor.intercept(MybatisQueryInterceptor.java:49)

………………

Caused by: java.io.IOException: Tried to send an out-of-range integer as a 2-byte value: 48857
	at org.postgresql.core.PGStream.sendInteger2(PGStream.java:275)
	at org.postgresql.core.v3.QueryExecutorImpl.sendParse(QueryExecutorImpl.java:1507)
	at org.postgresql.core.v3.QueryExecutorImpl.sendOneQuery(QueryExecutorImpl.java:1830)
	at org.postgresql.core.v3.QueryExecutorImpl.sendQuery(QueryExecutorImpl.java:1393)
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:303)
	... 170 common frames omitted

通过跟踪下来发现
postgresql对于sql语句的参数数量是有限制的,最大为32767。

postgresql源代码为:

public void sendInteger2(int val) throws IOException {
        if (val >= -32768 && val <= 32767) {
            this.int2Buf[0] = (byte)(val >>> 8);
            this.int2Buf[1] = (byte)val;
            this.pgOutput.write(this.int2Buf);
        } else {
            throw new IOException("Tried to send an out-of-range integer as a 2-byte value: " + val);
        }
    }

也就是说 pgsql使用2个字节的integer,故其取值范围为[-32768, 32767]。
但是我们代码在传参数的时候 已经到了 48857;因此 导致不能正常执行;

于是将分批次执行:

public static List<List<Long>> splitBatchsparams(List<Long> list){
    List<List<Long>> returnList = new ArrayList<>();
    int numberBatch = 32767; //参数最大个数
    double number = list.size() * 1.0 / numberBatch;
    int n = ((Double)Math.ceil(number)).intValue(); //向上取整
    for(int i = 0; i < n; i++){
        int end = numberBatch * (i + 1);
        if(end > list.size()){
            end = list.size(); //如果end不能超过最大索引值
        }
        returnList.add(list.subList(numberBatch * i , end));
    }
    return returnList;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值