• JdbcTemplate数据库连接耗尽问题排查


    目录

    问题起因

    排查思路

    步骤一:通过jvisualvm查看线程情况

    步骤二:在代码中通过打印dbcp可用连接数

    步骤三:顺着源代码看 jdbcTemplate.queryForStream

    解决方案

    思考


    问题起因

    使用 JdbcTemplate+dbcp连接池进行数据库访问

    dbcp配置最大连接为10

    1. @Bean
    2. public BasicDataSource dataSource() {
    3. BasicDataSource ds = new BasicDataSource();
    4. ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
    5. ds.setUrl("jdbc:mysql://localhost:3306/xxx");
    6. ds.setUsername("root");
    7. ds.setPassword("xxxx");
    8. ds.setInitialSize(5);
    9. ds.setMaxTotal(10);
    10. return ds;
    11. }

    JdbcTemplate配置为

    1. @Bean
    2. public JdbcTemplate jdbcTemplate(javax.sql.DataSource dataSource) {
    3. return new JdbcTemplate(dataSource);
    4. }

    使用的代码为

    1. public List selectByName() {
    2. String sql = "select * from base_sku where sku_name like '%瓜';";
    3. Stream baseSkuDOStream = jdbcTemplate.queryForStream(sql, new BaseSkuDoRowMapper());
    4. List baseSkuDOs = baseSkuDOStream.collect(Collectors.toList());
    5. return baseSkuDOs;
    6. }

    代码运行10次后,代码夯住,不能继续运行

    排查思路

    步骤一:通过jvisualvm查看线程情况

    发现一直卡在获取数据库连接处,表明获取不到数据库连接,怀疑连接耗尽了

    步骤二:在代码中通过打印dbcp可用连接数

    System.out.println("dbcp连接池可用连接:"+basicDataSource.getNumIdle() 

    打印结果:

    dbcp连接池可用连接:0 

    的确被耗尽,所以推断是连接没有释放

    在网上查询JdbcTemplate使用连接是自动释放的,无需手动释放

    但这里的确没有归还

    步骤三:顺着源代码看 jdbcTemplate.queryForStream

    发现调用execute时,stream方法中传的关闭资源是false

    也就是说 jdbcTemplate.queryForStream 这个方法不会自动关闭连接

    所以应该需要手动close 资源

    解决方案

    在代码中加入stream的close,运行果然能释放连接了

    1. public List selectByName() {
    2. String sql = "select * from base_sku where sku_name like '%瓜';";
    3. Stream baseSkuDOStream = jdbcTemplate.queryForStream(sql, new BaseSkuDoRowMapper());
    4. List baseSkuDOs = baseSkuDOStream.collect(Collectors.toList());
    5. //加入stream关闭
    6. baseSkuDOStream.close();
    7. return baseSkuDOs;
    8. }

    思考

    所以猜这里的stream这种模式,是不会自动关闭的,看一下其他调用jdbcTemplate.execute的地方,果然,除了queryForStream方法

    其他的都是可以自动关闭的,看来是遇到坑了,下次一定切记,jdbcTemplate 使用queryForStream方法一定要手动关闭连接。

    遇到数据库连接相关问题以后可以按照此思路排查。

  • 相关阅读:
    Numpy基础入门知识点总结
    LeetCode50天刷题计划(Day 31— 插入区间(9.00-11.20)
    【教3妹学算法】矩形面积 II
    B. Stairs
    PostgreSQL13 安装
    Redis-05Redis应用场景
    MyBatis的相应API与传统和代理开发的Dao层实现
    SpringBoot+Vue实现前后端分离的企业人事管理系统
    统一数据返回格式的实现
    File中文件改名
  • 原文地址:https://blog.csdn.net/u010916254/article/details/127091549