環境:mysql
持久層:JPAsql
數據庫鏈接池:druid數據庫
數據庫中間件:Mycatui
數據庫:Mysql線程
報錯:orm
Unable to acquire JDBC Connection中間件
排查步驟:blog
方法一:事務
一、druid配置沒有問題。ssl
二、Mysql鏈接數正常,可是發現mysql有不少連接沒有釋放。(用root用戶執行:show full processlist ; 指令)
如圖:發現不少State = Sleep的連接,連接都很長,一直不釋放連接。
三、kill掉相應的連接。(由於業務數據不是很重要,爲了先恢復功能,用此下策)
四、接着排查代碼。發現JPA的save方法,默認更新一條記錄使用以下方式:update tb_name set xxx = xxx where id = xxx ; 使用默認的主鍵進行數據的更新。而業務側,因爲數據龐大使用了數據庫的分庫分表,mycat做爲數據庫中間件,該表的路由規則爲:根據用戶id去摸,進行數據的分庫分表。
問題緣由找到:每次執行更新(save)方法時,Mycat都會廣播這條sql,當數在插入時,就形成更新方法阻塞等待(鎖,事務相關),致使連接不釋放。
方法二:
一、查看mysql事務表,獲得thread_id : select * from information_schema.INNODB_TRX ; 從結果中的:trx_mysql_thread_id 獲得線程id
二、select * from performance_schema.threads where THREAD_ID = 第一步獲得的線程id (這一步能夠不執行,目的只是爲了演示mysql的線程管理,以及相應的查看方法。)
三、select * from performance_schema.events_statements_current where THREAD_ID = 第一步獲得的線程id ; 根據 SQL_TEXT 獲得相應的sql語句。
以上就是mysql經過阻塞的線程,找到代碼中相應的sql的方法。
解決方法:
一、寫sql,在更新數據時,修改JPA默認的方式,使用路由規則去更新數據。