CannotGetJdbcConnectionException

描述

  • 此异常具体为:

Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Conne
ction; nested exception is java.sql.SQLException: Connections could not be acquired from the underlying database!

  • 这是出现在线上环境的一个报错,时不时就会报错,报错后过段时间可能又好了,影响接口的访问和代码的运行,项目为ssm结构的一个项目,用的数据库连接池为c3p0,问题出现在重新系统后,重装mysql数据库(msi安装版5.7)出现的问题,ssm程序没有更新还是重装系统之前的程序。

处理

  • 通过异常可以看出是数据库获取不到连接,排查是通过下面的mysql查看连接的相关指令,看看是否存在很多连接,看看具体的连接是哪些,有没有存在恶意攻击,看看当前连接数是否超过了数据库最大的连接数等。
#查看具体的每条连接
show processlist;

# 查看当前连接数
SHOW STATUS LIKE 'Threads%';

# 查看连接数具体的IP
SELECT substring_index(host, ':',1) AS host_name,state,count(*) FROM information_schema.processlist GROUP BY state,host_name;

# 查看数据库最大的连接数
SHOW VARIABLES LIKE '%max_connections%';

# 修改最大连接数(不用重启数据库,实时生效,重启后会失效)
set global max_connections=500;

  • 在线上环境,通过查询当前连接数为152,通过查看具体的连接IP都是localhost,而数据库最大的连接数是150(msi安装版5.7默认为151),可以看到这里已经超出了,再去看看ssm程序的数据库最大连接池数量配置为的是200。
    从这些数据可以看出,就是ssm程序的连接池是200,然后数据库最大连接数又配置为150,所以连接池在获取连接时,有50的是有问题的,如果获取到是有问题的,可能就会造成CannotGetJdbcConnectionException异常。(猜测)
    ssm程序还在运行时,修改最大连接数为500后,再查看当前连接数,可以看到连接数即变成了211,说明ssm程序所需的连接最高的场景至少应该为211条,再次验证可能就是这个问题导致的CannotGetJdbcConnectionException异常。(猜测)

后续

上面的猜测可能是造成问题的部分原因。后续还是会出现,后续排查是可能大量客户端同时状态变化发到ssm程序(这个操作实际上是客户端变化就会调用某个查询接口)导致设定的200连接数被打满,然后后台就一直报错CannotGetJdbcConnectionException,如果期间有其他需要查询的操作,比如平台访问接口显示数据,此时由于获取不到相应的mysql链接,所以就显示不了数据,一直堵塞了。
还有有时候也要考虑mysql8小时自动关闭空闲连接的问题,然后c3p0认为那个被关闭的连接还有效而去使用然后报错的问题。
此外还要考虑c3p0自动关闭空闲连接的时间不能高于mysql设定的interactive_timeout和wait_timeout。

参考

too many connections 解决方法
https://blog.csdn.net/qq_31454017/article/details/71108278
mysql sleep详解_MySQL Sleep进程
https://blog.csdn.net/weixin_36166342/article/details/112952852
c3p0数据库连接池 “too many connections” 解决方法
https://blog.csdn.net/qq_42168462/article/details/104908982
c3p0连接池maxIdleTime小于mysql数据库interactive_timeout参数导致出现NewPooledConnection close Exception的解决办法
https://blog.csdn.net/Caption_Jack_Sparrow/article/details/50662184
MySQL中的配置参数interactive_timeout和wait_timeout(可能导致过多sleep进程的两个参数)
https://blog.csdn.net/keketrtr/article/details/110040523
MySQL连接超时相关的两个参数interactive_timeout和wait_timeout的区别和解释
https://blog.csdn.net/mawenshu316143866/article/details/82381202
C3P0连接池配置参数讲解
https://cloud.tencent.com/developer/article/2032870
使用C3P0连接MySQL出现大量的Sleep状态连接的处理方法
https://www.javatang.com/archives/2016/09/28/51481419.html
8小时mysql失效处理
https://www.php.cn/mysql-tutorials-130755.html
关于MySQL的wait_timeout连接超时问题报错解决方案
https://blog.csdn.net/lijingjingchn/article/details/116566264

修改mysql配置文件my.ini后,重启mysql服务一直失败

注意

此文件发生在windows的mysql5.7.msi安装版本上, 其他版本不一定会出现。

描述

有个需求需要配置mysql的最大连接数,由于执行sql语句set global max_connections的话,重启mysql就无效了,会恢复成默认的151,所以想修改配置文件my.ini达到永久的配置。

找到C:\ProgramData\MySQL\MySQL Server 5.7\my.ini的配置文件,用系统默认的记事本打开,在[mysqld]下添加max_connections=500后,按ctrl+a保存,退出记事本。

然后在任务管理器服务里面找到mysql对应的服务重启,这时候会发现一直卡在启动中,还怀疑是笔记本修改的时候修改错了,因为my.ini里面默认已经有了max_connections=151配置,还以为是多配置了一个max_connections导致的,删除,重启还是发现卡在启动中。

后面发现直接改成原来的151还是会卡在启动中。

处理

1.服务卡在启动中,先cmd执行taskkill/f /t /im mysqld.exe,停止mysql运行
2.打开my.ini文件后,修改后,选择文件另存为,重新另存为ANSI编码,然后覆盖原utf-8的编码文件
3.任务管理器服务里面找到mysql对应的服务重启,或者cmd执行net start XXX (XXX为服务名,默认是MYSQL57)
4.你会发现启动成功了,造成这个问题估计是文件编码的原因,mysql配置文件默认是ANSI编码格式,windows自带的记事本修改后默认保存成了UTF-8。

参考

修改msyql的my.ini文件后重启mysql服务,服务无法启动
https://blog.csdn.net/sumjob/article/details/124887425