美文网首页
在定时任务中使用jdbcTemplate之后,上线后数据库出现死

在定时任务中使用jdbcTemplate之后,上线后数据库出现死

作者: maxbin | 来源:发表于2017-10-30 16:40 被阅读717次

    问题描述

    • 项目中需要定时同步会员系统司机(会员)数据,为了简化开发,直接使用jdbcTemplate作为数据库连接;
    • 项目测试时候一切正常,等到上线后,第二天IT支持反映问题说,司机表无法操作,紧急排查问题后发现是锁表了;

    解决方案

    1. 根据数据库锁表的时间,以及业务,判断是新上线的定时任务导致的问题;
    2. 因为设计后的编码工作是交给实习生完成的,心里一下没底了,可能编码出现了问题,感觉自查编码逻辑:
    // 获取连接
    con = jdbcTemplate.getDataSource().getConnection();
    // 执行SQL
    jdbcTemplate.execute(sql.toString());
    con.close();
    

    代码逻辑部分只有一条更新的sql语句,因为jdbc默认是自动提交任务的,断点调试确认也是这样的,按道理不会造成死锁才对;
    重复测试,压测一直都无法找到原因,然后电脑起着不动,吃饭后回来发现出现死锁的问题了,难道是起的时间长了才会出问题?
    继续用多台电脑压测,多线程继续(其实生产只起了一个job任务实例);
    此时任然找不到原因,迷茫中。。。
    断点调试,发现程序跑了一段时间之后,连接的自动提交属性变为false了,冷静分析,应该是被别的程序改了,此时继续查别人的代码:

    con = jdbcTemplate.getDataSource().getConnection();
    con.setAutoCommit(false); // 关键在这里
    
    jdbcTemplate.execute(DELETE_SQL);
    String sql = getSql(DateUtils.format(new Date()), DateUtils.format(new Date()), getCurrentStartTime());
    LOG.info("execute sql={}", sql);
    jdbcTemplate.execute(sql);
    con.commit();
    con.close();
    

    此时问题才算是找到了,分析问题导致的原因:

    1. 先看一下jdbcTemplate的配置
    spring.datasource.url=${db.url}
    spring.datasource.username=${db.user}
    spring.datasource.password=${db.password}
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.test-on-borrow=true
    spring.datasource.max-active=10
    spring.datasource.validation-query=select 1
    
    1. spring.datasource.max-active=10参数说明默认最大是10个连接数;连接池是在使用时创建,用完归还连接,但是归还连接时连接的属性并不会变更,所以如果有其他程序改变了连接的默认属性,此时最好手动改回来;
    2. 解决方案:一、在自己不需要事务的业务代码中,可以在获取连接后,将autoCommit属性设置为true;
      二、或者在自己手动更改过连接池属性后,如果多人开发公用此连接,最好是再改回默认设置;

    方法一

    // 获取连接
    con = jdbcTemplate.getDataSource().getConnection();
    if(!con.getAutoCommit()){
      con.setAutoCommit(true); // 关键在这里
    }
    // 执行SQL
    jdbcTemplate.execute(sql.toString());
    con.close();
    

    方法二

    con = jdbcTemplate.getDataSource().getConnection();
    con.setAutoCommit(false); // 关键在这里
    
    jdbcTemplate.execute(DELETE_SQL);
    String sql = getSql(DateUtils.format(new Date()), DateUtils.format(new Date()), getCurrentStartTime());
    LOG.info("execute sql={}", sql);
    jdbcTemplate.execute(sql);
    con.commit();
    con.setAutoCommit(true); // 关键在这里
    con.close();
    

    jdbc在项目中不常用,偶尔用到也会犯错误,记一下,为今后寻找问题多一份依据。

    相关文章

      网友评论

          本文标题:在定时任务中使用jdbcTemplate之后,上线后数据库出现死

          本文链接:https://www.haomeiwen.com/subject/awwppxtx.html