凯发k8国际娱乐官网入口-k8凯发> 分布式数据库中间件 ddm> > > 如何解决jdbc驱动方式连接ddm异常问题
更新时间:2022-08-12 gmt 08:00

如何解决jdbc驱动方式连接ddm异常问题-凯发k8国际娱乐官网入口

mysql驱动( jdbc)通过loadbalance方式连接ddm,在某些场景下连接切换时会陷入死循环,最终导致栈溢出。

问题定位

  1. 查看app日志,定位异常原因。
    例如,从以下日志中分析出异常最终原因为栈溢出。
    caused by: java.lang.stackoverflowerror
         at java.nio.heapbytebuffer.(heapbytebuffer.java:57)
         at java.nio.bytebuffer.allocate(bytebuffer.java:335)
         at java.nio.charset.charsetencoder.encode(charsetencoder.java:795)
         at java.nio.charset.charset.encode(charset.java:843)
         at com.mysql.jdbc.stringutils.getbytes(stringutils.java:2362)
         at com.mysql.jdbc.stringutils.getbytes(stringutils.java:2344)
         at com.mysql.jdbc.stringutils.getbytes(stringutils.java:568)
         at com.mysql.jdbc.stringutils.getbytes(stringutils.java:626)
         at com.mysql.jdbc.buffer.writestringnonull(buffer.java:670)
         at com.mysql.jdbc.mysqlio.sqlquerydirect(mysqlio.java:2636)
  2. 分析溢出源。
    例如,从以下日志可以分析出,溢出原因为驱动内部陷入死循环。
    at com.mysql.jdbc.loadbalancedconnectionproxy.picknewconnection(loadbalancedconnectionproxy.java:344)
    at com.mysql.jdbc.loadbalancedautocommitinterceptor.postprocess(loadbalancedautocommitinterceptor.java:104)
    at com.mysql.jdbc.mysqlio.invokestatementinterceptorspost(mysqlio.java:2885)
    at com.mysql.jdbc.mysqlio.sqlquerydirect(mysqlio.java:2808)
    at com.mysql.jdbc.connectionimpl.execsql(connectionimpl.java:2483)
    at com.mysql.jdbc.connectionimpl.setreadonlyinternal(connectionimpl.java:4961)
    at com.mysql.jdbc.connectionimpl.setreadonly(connectionimpl.java:4954)
    at com.mysql.jdbc.multihostconnectionproxy.syncsessionstate(multihostconnectionproxy.java:381)
    at com.mysql.jdbc.multihostconnectionproxy.syncsessionstate(multihostconnectionproxy.java:366)
    at com.mysql.jdbc.loadbalancedconnectionproxy.picknewconnection(loadbalancedconnectionproxy.java:344)
  3. 查看使用的mysql版本,为5.1.44。

    查看该版本源代码,发现获取连接时,loadbalance会根据负载均衡策略更新连接,并将老连接的配置复制给新连接,在新连接autocommittrue,新连接部分参数和老连接不一致,loadbalanceautocommitstatementthreshold参数没有配置的场景下,会陷入死循环,更新连接函数调用同步参数函数,同步参数又调用更新连接,最终导致栈溢出。

解决方法

在连接ddm的url添加loadbalanceautocommitstatementthreshold=5&retriesalldown=10参数。

//使用负载均衡的连接示例
//jdbc:mysql:loadbalance://ip1:port1,ip2:port2..ipn:portn/{db_name}
string url = "jdbc:mysql:loadbalance://192.168.0.200:5066,192.168.0.201:5066/db_5133?loadbalanceautocommitstatementthreshold=5&retriesalldown=10";
  • loadbalanceautocommitstatementthreshold:表示连接上执行多少个语句后会重新选择连接。

    假设loadbalanceautocommitstatementthreshold设为5,则当执行5个sql后(queries或者updates等),将会重新选择连接。若为0表示“粘性连接,不重新选择连接”。关闭自动提交时(autocommit=false)会等待事务完成再考虑是否重新选择连接。

分享:

more

网站地图