环境: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默认的方式,使用路由规则去更新数据。