一個MySQL-JDBC驅動bug引發的血案……

問題背景sql

公司是作電商系統的,整個系統搭建在華爲雲上。系統設計的時候,考慮到後續的用戶和訂單數量比較大,須要使用一些大數據庫的組件。關係型數據庫這塊,考慮到後續數據量的快速增加,不是直接寫入MySQL,而是使用了華爲雲的分佈式數據庫中間件DDM使用了DDM以後,能夠在業務不感知的狀況下,直接增長MySQL讀實例的個數,線性提高讀性能。也支持中間件層面的分庫分表,提供海量關係型數據庫的操做。簡直是爲電商系統貼身定製的。數據庫

DDM自身是以集羣形式提供服務的,對業務開放的是多個鏈接IP地址。須要有一層負載均衡。若是使用傳統的加LB的形式作負載均衡,會多一層中轉,有性能損耗。因此,直接使用了MySQL-JDBC提供的客戶端負載均衡能力。負載均衡

邏輯結構以下圖所示:分佈式

▲業務經過MySQL-JDBC的Loadbalance能提訪問多個DDM節點。MySQL-JDBC提供負載均衡能力。post

 

問題說明性能

MySQL JDBC驅動的客戶端負載均衡能力,一直運行得好好,性能嗷嗷叫。但是前一陣子竟無端出現業務請求失敗。我是負責電商訂單模塊的,涉及到真實的Money,這個問題可嚇了寶寶一身冷汗……測試

因而趕忙查看了後臺日誌,發現是訪問DDM出現了異常,二話不說直接提了工單給華爲雲DDM服務。大數據

不得不說,華爲雲的服務仍是很好的,不到半個小時就有專門的工做人員聯繫了我,還跟我一塊兒排查問題。ui

將咱們業務的日誌取下來,和DDM的支撐人員一塊兒分析,發現報錯以下:根本緣由居然是MySQL驅動的bug,致使StackOverflow本地棧溢出致使……原來是一個Bug引起的血案,誤會了DDM服務,真是抱歉了設計

從堆棧能夠看出來,某個異常,觸發了MySQL-JDBC的bug,致使循環調用,直至棧溢出。在華爲DDM支撐人員的建議下,對驅動代碼進行了反編譯,從反編譯的狀況下,能夠看到的確是存在循環嵌套的可能。

 

Loadbalance輪詢鏈接 –>同步新老鏈接的狀態 ->發送sql給服務端 -> Loadbalance輪詢鏈接。

相關代碼以下:

 

這麼明顯的bug,不太相信MySQL會沒有發現。當前咱們使用的是5.1.44版本的驅動,查看了下最新的5.1.66的代碼,發現的確是修復了這個問題的,代碼以下:

 

經過過濾掉SET和SHOW語句,避免了循環嵌套的發生。

可是5.1.66又引入了新的bug,因爲並非每一個調用postProcess的地方都有SQL,這裏的代碼會拋空指針異常。MySQL JDBC的開發者都不作測試的嗎……

沒辦法,分析了下5.1.44的代碼,發現經過適當的調整loadBalanceAutoCommitStatementThreshold這個參數的數值,也能夠避免循環嵌套的發生。咱們的環境改爲了5,修改以後,平穩運行1周,沒再出現過問題。

 

修改方案

loadBalanceAutoCommitStatementThreshold修改爲了5,可是引入的問題是,若是業務包含一些比較耗時的SQL,可能會致使DDM的負載不均衡。不過,就目前狀況來看,DDM的性能仍是比較強勁的~

點擊這裏,免費體驗一番吧!

相關文章
相關標籤/搜索