如何解決JDBC驅動方式連接DRDS異常問題
MySQL驅動( JDBC)通過Loadbalance方式連接DRDS,在某些場景下(xia)連接切換(huan)時會(hui)陷入(ru)死循環(huan),最終(zhong)導(dao)致棧溢出。
問題定位
- 查看APP日志,定位異常原因。
例(li)如,從(cong)以下日志(zhi)中(zhong)分析出(chu)異常最(zui)終原(yuan)因(yin)為(wei)棧(zhan)溢出(chu)。
Caused by: java.lang.StackOverflowError
at java.nio.HeapByteBuffer.<init>(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)
- 分析溢出源。
例如,從以下(xia)日(ri)志可(ke)以分析(xi)出,溢出原(yuan)因(yin)為驅(qu)動(dong)內部陷入死循環。
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)
- 查看使用的MySQL版本,為5.1.44。
查看該版本源代碼,發現獲取連接時,LoadBalance會根據負載均衡策略更新連接,并將老連接的配置復制給新連接,在新連接AutoCommit為 true ,新連接部分參數和老連接不一致,loadBalanceAutoCommitStatementThreshold參(can)(can)數(shu)(shu)沒(mei)有配置的(de)場景(jing)下,會陷入死循環,更(geng)新(xin)連接(jie)函(han)數(shu)(shu)調(diao)用(yong)(yong)同(tong)步(bu)參(can)(can)數(shu)(shu)函(han)數(shu)(shu),同(tong)步(bu)參(can)(can)數(shu)(shu)又(you)調(diao)用(yong)(yong)更(geng)新(xin)連接(jie),最終導致棧溢出。
解決方法
在連接DRDS的URL添(tian)加**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";
備注:
1、loadBalanceAutoCommitStatementThreshold:表示(shi)連(lian)接上(shang)執行多少個語句后會重新選擇(ze)連(lian)接。
2、假(jia)設(she)loadBalanceAutoCommitStatementThreshold設(she)為5,則當執行(xing)5個sql后(Queries或者updates等(deng)),將會重(zhong)新選(xuan)擇連(lian)接(jie)。若為0表示“粘(zhan)性(xing)連(lian)接(jie),不重(zhong)新選(xuan)擇連(lian)接(jie)”。關閉自動提交時(autocommit=false)會等(deng)待(dai)事務完成再考慮是否重(zhong)新選(xuan)擇連(lian)接(jie)。
使用mysqldump從MySQL導出數據非常緩慢的原因
mysqldump客戶端的版本(ben)(ben)和DRDS所支持的MySQL版本(ben)(ben)不(bu)一致,可(ke)能會導(dao)致從MySQL導(dao)出(chu)數據非常(chang)緩慢。
建議版本保持一致。
導入數據到DRDS過程中出現主鍵重復
要避(bi)免導(dao)入數據到DRDS過程(cheng)中出現主鍵(jian)重復的現象,需要在DRDS中創表時(shi)設置自(zi)增起始值。還要確保(bao)起始值大于導(dao)入數據自(zi)增鍵(jian)的最(zui)大值。
如何處理數據遷移過程中自增列報錯:主鍵重復
重(zhong)新(xin)設(she)置自增主鍵的初始值為大(da)于當(dang)前已(yi)有數據的最大(da)值,執行(xing)如下語句(ju):
ALTER SEQUENCE 庫名(ming).SEQ名(ming) START WITH 新初始(shi)值
如何處理配置參數未超時卻報錯
如果發(fa)現(xian)配置參數(shu)未(wei)超時卻報錯的現(xian)象,建(jian)議可將參數(shu)SocketTimeOut值進行調整或者去掉。默認為0則不斷開(kai)連接。
如何處理DRDS邏輯庫與RDS實例的先后關系
DRDS邏(luo)輯(ji)庫與關聯的(de)RDS強相關,不允(yun)許直接刪(shan)除關聯的(de)RDS,這會導致業務不可用且邏(luo)輯(ji)庫也會刪(shan)除失敗(bai)。如果需要(yao)刪(shan)除,先(xian)刪(shan)除邏(luo)輯(ji)庫再刪(shan)除RDS。
DRDS邏輯庫刪除后,數據節點里面殘留著部分預留的DRDS數據庫和一些DRDS的帳戶,這些是否需要手動刪除
如果(guo)不需要(yao)了,可以直接(jie)手動刪除,釋放空間。