概述
背景
用servlet+jsp+mysql开发一个练手项目在线商城,dao层选用HikariDP连接池作为数据源,网页前端点一点,刷新几次之后,即进行几次数据库操作之后,就会报错too many connection
解决思路
报这个错误意思是连接数过多,我们都知道,连接数据库获取的连接数是有上限的,虽然上限可以设置,但是就我这么小的小项目,mysql不至于顶不住啊?另外,所有的获取连接操作,我都是try-with-resource代码块实现的,也就是说,所有获取的connection,在使用之后都正常释放了。那么问题点可能出现在三部分:
- try-with-resource代码没有正确释放connection
- 数据库连接池配置的连接数太少,不够支撑我们的项目
- mysql达到连接数上限
求证
1.针对try-with-resource是否正确释放connection问题,查了资料理论上来讲应该是可以释放connection回到连接池的,连接池已经实现了AutoCloseable接口。
为了求证,我把try-with-resource代码修改成传统的try catch finally进行测试,结果还是失败,说明问题不出在这。
2.数据库连接池是否有问题?我把连接池去掉,直接采用传统的DriverManager获取连接,发现,问题解决了!说明问题一定出在连接池这里!我一度认为,是因为数据库连接池配置的最大连接数太小了,虽然这和理论不符合,因为我的这个项目,最多同时也就七八个连接!下面是我的连接池配置代码。
public class DataSourceUtil {
...此处省略字符串常量
public static Connection getConn() throws SQLException {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(DB_URL);
config.setUsername(USER);
config.setPassword(PASS);
config.addDataSourceProperty("connectionTimeout", "1000"); // 连接超时 1s
config.addDataSourceProperty("idleTimeout", "60000"); // 空闲超时 60s
config.addDataSourceProperty("maximumPoolSize" , "10"); // 最大连接数 10
return new HikariDataSource(config).getConnection();
}
}
我调整了连接池的最大连接数为100,空闲超时为6秒,因为如果一个connection即使没被正确释放,空闲超过6秒也会被释放。经过实验发现,还是不行,说明,连接池配置没问题,这和我理论上的预期也是一致的!
3.那都没问题?出鬼了吗,去mysql看看,我通过终端连接到mysql后,通过命令show processlist;查看当前数据库的连接情况
这个是正常情况的连接数
启动项目后查看:好家伙,怎么这么多连接,即使是连接池,也应该只拿到10个连接才对,现在直接整了32个。
点一点项目中的功能后查看:我直接看傻了,为什么创建了153个连接,按理说1个数据库连接池拿到10个连接后,就会一直使用这10个,不会再申请了,真相只有一个!就是创建了多个数据库连接池!!
仔细分析下上面的代码可以发现:
return new HikariDataSource(config).getConnection();
这行代码是原罪…就是每调用一次getConn()方法都会new一个HikariDataSource,当然就会在mysql创建好多好多个连接,直到达到mysql的最大连接数!导致报错。
解决
数据库连接池对象只创建一个
public class DataSourceUtil {
// 注册驱动
static {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 数据库 URL
static final String DB_URL = "jdbc:mysql://localhost:3306/online_mall?useUnicode=true&characterEncoding=utf8";
// 数据库的用户名与密码,需要根据自己数据库的值设置
static final String USER = "root";
static final String PASS = "12345678";
static final HikariDataSource DATA_SOURCE = getDataSource();
public static HikariDataSource getDataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(DB_URL);
config.setUsername(USER);
config.setPassword(PASS);
config.addDataSourceProperty("connectionTimeout", "1000"); // 连接超时 1s
config.addDataSourceProperty("idleTimeout", "60000"); // 空闲超时 6s
config.addDataSourceProperty("maximumPoolSize" , "10"); // 最大连接数 100
return new HikariDataSource(config);
}
public static Connection getConn() throws SQLException {
return DATA_SOURCE.getConnection();
}
}
现在无论调用网页中怎么操作,连接都能正常获取和释放了,说明问题就出在这,现在再去查看一下Mysql连接的情况:
这就对了!符合预期!问题解决!
总结与反思
1.这个问题的原因是多么基本,多么简单,我本意是想封装一个getConn()方法,使用了错误的代码逻辑导致问题出现。
2.解决类似问题的思路就是肯定是连接数超过配置的值了,至于为什么超过,原因有很多,可能是代码问题、可能是conn使用后没有正确的释放,当然也可能是业务规模增加,mysql已经不支持如此大量的业务了。总之,这个问题出现的原因必然是conn数量过多,这也体现了对于昂贵资源的合理使用与释放的重要性!
3.数据库连接池拿到的连接在不用的时候,状态都是sleep的。
最后
以上就是潇洒外套为你收集整理的使用数据库连接池报异常too many connection的全部内容,希望文章能够帮你解决使用数据库连接池报异常too many connection所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复