【分布式数据库中间件 DDM】如何解决jdbc驱动方式连接DDM异常问题

目录

福利发放

问题现象

定位思路

解决方法


福利发放

目前华为云分布式数据库中间件DDM有试用体验活动,申请华为云账号后可以单击如下图片一键体验:

【分布式数据库中间件 DDM】如何解决jdbc驱动方式连接DDM异常问题_第1张图片

问题现象

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)会等待事务完成再考虑是否重新选择连接。

  • retriesAllDown:当所有的连接地址都无法连接时,轮询重试的最大次数。

    重试次数达到阈值仍然无法获取有效连接,将会抛出SQLException。

 

你可能感兴趣的:(分布式数据库,mysql,关系型数据库,华为云,DDM,云服务,分布式数据库,mysql)