在做项目的时候,项目运行一段时间后 出现 :An attempt by a client to checkout a Connection has timed out. 这个是因为连接池用光,无法获取连接了,
使用C3P0作为数据源的时候,经常出现连接池不够,不能获取连接 An attempt by a client to checkout a Connection has timed out.
出现这种情况绝对出现在连接没关闭,在什么下没关闭呢?
1:如果你手动从c3p0连接词获取连接,检查下有没有地方遗漏了忘记关闭
2:事务没提交,在某些地方使用了事务,事务挂起没提交,连接就不会关闭
我们项目就出现这个情况,使用Spring来管理事务的,因为一个方法里会调用多个方法,Spring事务就会等这些全部方法执行完后才会关闭连接,但是如果这个方法里有个循环,重复查询数据,一个SQL就会产生一个链接 那么连接池就会挂掉
调试方法可以在每个方法执行前后,输出当前连接池的使用情况,来监听
//首先注入C3p0的数据源
@Resource
ComboPooledDataSource cpds;
//添加一个方法
private void printC3p0Log() {
try {
System.out.println("---链接总数量" + cpds.getNumConnections() + "使用中的链接" + cpds.getNumBusyConnections() + "空闲的链接" + cpds.getNumIdleConnectionsAllUsers());
} catch (SQLException e) {
e.printStackTrace();
}
}
然后再每个SQL执行前后输出下,这样你回看到连接池数量暴增加(如果是在Spring事务管理,并且在一个方法)
解决方法:
1:如果SQL执行较长,优化他,或使用存储过程
2:强暴一点在方法上添加 @Transactional(propagation= Propagation.NOT_SUPPORTED) 或在读的方法上设置readOnly = true
3: 把这个方法分解成很多小方法,在各个方法上添加2 中的注解;
4:从DataSource中获取数据源(datasource.getConnection ,注意要手动提交,归还connection)