jdbc批量插入报错

各位老师好:

  1. springboot项目中,我使用jdbc批量插入时,报错:
    com.oceanbase.jdbc.internal.util.exceptions.MaxAllowedPacketException: query size (4194308) is >= to max_allowed_packet (4194304)
  2. 我用obclient设大了这个参数值,byte数增加10倍,设为41943040:
    obclient> SET GLOBAL max_allowed_packet=41943040;
    这时再用jdbc运行批量插入语句,又报这个错了:
    java.sql.SQLNonTransientConnectionException: (conn=2388917) packet sequence mismatch, expected obSeqNo=3, but received obSeqNo=1 at com.oceanbase.jdbc.internal.util.exceptions.ExceptionFactory.createException(ExceptionFactory.java:122) ~[oceanbase-client-2.4.3.jar:?]

如何才能使jdbc批量插入执行正常,请老师们指导一哈。感恩您!

补充:
看管网介绍说, max_allowed_packet这个参数,客户端与 Server 端一般均需要调整。
所以, 个人分析有没有可能,我需要在application.yml的数据源url或者其他参数中设置max_allowed_packet参数呢?且暂时没找到如何设置!

什么版本的ob呢?

连接配置方便发一下吗?直连2881还是连的2883

每一批是多少条?这种用预编译的批量更好,不要用multiQuery这种字符串拼接了。
打开useServerPrepare参数

useServerPrepStmts:默认为false. 是否使用服务器prepare开关

jdbc客户端参数:

cachePrepStmts:默认false.是否缓存prepareStatement对象。每个连接都有一个缓存,是以sql为唯一标识的LRU cache. 同一连接下,不同stmt可以不用重新创建prepareStatement对象。

prepStmtCacheSize:LRU cache中prepareStatement对象的个数。一般设置为最常用sql的个数。

prepStmtCacheSqlLimit:prepareStatement对象的大小。超出大小不缓存。

Jdbc对prepare的处理过程:

useServerPrepStmts=true时Jdbc对prepare的处理

1) 创建PreparedStatement对象,向服务器发送COM_PREPARE命令,并传送带问号的sql. 服务器返回jdbc stmt->id等信息

2) 向服务器发送COM_EXECUTE命令,并传送参数信息。

useServerPrepStmts=false时Jdbc对prepare的处理

1) 创建PreparedStatement对象,此时不会和服务器交互。

2) 根据参数和PreparedStatement对象拼接完整的SQL,向服务器发送QUERY命令

我们再看参数cachePrepStmts打开时在useServerPrepStmts为true或false时,均缓存PreparedStatement对象。只不过useServerPrepStmts为的true缓存PreparedStatement对象包含服务器的stmt->id等信息,也就是说如果重用了PreparedStatement对象,那么就省去了和服务器通讯(COM_PREPARE命令)的开销。而useServerPrepStmts=false是,开启cachePrepStmts缓存PreparedStatement对象只是简单的sql解析信息

麻烦告知一下JDBC、OBProxy、OBServer的版本

  1. JDBC版本是:com.oceanbase:oceanbase-client:2.4.3
  2. OB安装版本为:社区版,5.7.25-OceanBase_CE-v4.1.0.1
  3. springboot数据源连接信息为:
    type: com.zaxxer.hikari.HikariDataSource
    jdbcUrl: jdbc:oceanbase://172.16.29.xx:2883/dwd_test
    driver-class-name: com.oceanbase.jdbc.Driver
    username: root
    password: 123456
    pool-name: HikariCP-dwd
    #最小空闲连接数
    minimum-idle: 10
    #空闲连接存活最大时间,默认2分钟
    idle-timeout: 120000
    #连接池最大连接数,默认是10
    maximum-pool-size: 30
    #此属性控制从池返回的连接的默认自动提交行为,默认值:true
    auto-commit: true
    #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
    max-lifetime: 1800000
    #数据库连接超时时间,默认30秒
    connection-timeout: 30000
    #连接测试query
    connection-test-query: SELECT 1

obproxy的版本是啥?

[root@ecs-0416-sjai-1-002 ~]# obclient -V
obclient Ver Distrib 10.4.18-MariaDB, for Linux (x86_64) using readline 5.1

不是obclient,是obproxy
bin/obproxy -V

[root@ecs-0416-sjai-1-002 ~]# /root/obproxy/bin/obproxy -V
/root/obproxy/bin/obproxy -V
obproxy (OceanBase 4.1.0.0 7)
REVISION: 1-local-bacd5fac165346eb0fe09b906cc409738cffb58d
BUILD_TIME: Mar 22 2023 18:37:39

jdbc参数加一个试试。useOceanBaseProtocolV20=false

老师好:我是用的 PreparedStatement.executeBatch()操作的插入,一个批次1万条记录。
感谢你的提示,我试试看

现在还有问题吗

解决了,总结下
一、社区版-v4.1.0.1
1)增大max_allowed_packet值,
obclient> SET GLOBAL max_allowed_packet=自己根据情况定义,单位为byte;
2)方法一:jdbc链接增加useOceanBaseProtocolV20=false ##不使用ob2.0协议
方法二:jdbc链接增加useServerPrepStmts=true ##使用服务器prepare
二、社区版-v4.2.1.1
增大max_allowed_packet值即可:
obclient> SET GLOBAL max_allowed_packet=自己根据情况定义,单位为byte;

感恩 @张雨齐 @序风 大佬的指点,祝ob越来越好!