HikariPool-1 - Connection is not available
在springboot项目中出现一个问题,该问题从字面意思上说是数据链池链接资源已全部使用完毕,没有可用的链接使用
排查问题发现原因是:
sql由于参数填写错误,进行了全表扫描,由于返回数据量过大导致数据卡在映射层,导致资源卡死的情况,每调用一次就会损失一个链接资源,当所有链接资源都使用完毕时候,就出现以上的情况。
所以在写sql时一定要注意分页处理,避免这种情况。
导致卡死 分为两种情况
第一种是 卡在数据库层 : 就是当前执行的sql过去复杂又没有索引,一直处于在运行状态没有结果返回。
第二种是 卡住程序映射层 : 就是数据量过大,数据库里面的大量数据映射到程序中这个过程过去长,而jdbc本身又没有处理这种情况的方式。
我们以spring 提供的 JdbcTemplate 为列
第一种解决方案
设置jdbc自带的queryTimeOut() 的方法,在一定时间内未返回数据 就自动断开链接释放资源。
第二种解决方案
jdbc本身没有处理这种情况的能力,会一直等待响应,我们需要重写他们的方法,设定一定时间,如果超过这个时间还没有返回数据出来,就手动抛出异常,释放链接资源
关键代码
//需要其他方法时,自行重写 public class JdbcTemplateWapper extends JdbcTemplate { /** * 查询超时时间 */ public static int queryTimeout = 30; //数据读取超时时间 ms public static long readTimeOut = 10000;//ms private final JdbcTemplate jdbcTemplate; public JdbcTemplateWapper(JdbcTemplate jdbcTemplate){ this.jdbcTemplate = jdbcTemplate; this.jdbcTemplate.setQueryTimeout(queryTimeout); } @Override public <T> List<T> queryForList(String sql, Class<T> elementType) throws DataAccessException { return jdbcTemplate.query(sql, new SingleColumnRowMapperWapper(elementType)); } @Override public List<Map<String, Object>> queryForList(String sql) throws DataAccessException { return jdbcTemplate.query(sql, new ColumnMapRowMapperWapper()); } @Override public List<Map<String, Object>> queryForList(String sql, Object... args) throws DataAccessException { return jdbcTemplate.query(sql, args, new ColumnMapRowMapperWapper()); } public Map<String, Object> queryForMap(String sql, @Nullable Object... args) throws DataAccessException { return result(jdbcTemplate.queryForObject(sql, args, new ColumnMapRowMapperWapper())); } @Override public Map<String, Object> queryForMap(String sql) throws DataAccessException { return result(jdbcTemplate.queryForObject(sql, new ColumnMapRowMapperWapper())); } private static <T> T result(@Nullable T result) { Assert.state(result != null, "No result"); return result; } public class ColumnMapRowMapperWapper extends ColumnMapRowMapper{ long startDate = 0l; @Override protected Object getColumnValue(ResultSet rs, int index) throws SQLException { if(startDate <= 0l) startDate = new Date().getTime();//记录第一次读取的时间 为开始时间 if(startDate+readTimeOut < System.currentTimeMillis()) throw new SQLException("数据读取超时"); return super.getColumnValue(rs, index); } } public class SingleColumnRowMapperWapper<T> extends SingleColumnRowMapper<T>{ SingleColumnRowMapperWapper(Class<T> requiredType){ super(requiredType); } long startDate = 0l; @Override public T mapRow(ResultSet rs, int rowNum) throws SQLException { if(startDate <= 0l) startDate = new Date().getTime();//记录第一次读取的时间 为开始时间 else if(startDate+readTimeOut < System.currentTimeMillis()) throw new SQLException("数据读取超时"); return super.mapRow(rs, rowNum); } } }
本文来自博客园,作者:lanwf,转载请注明原文链接:https://www.cnblogs.com/lccsdncnblogs/p/17526214.html