connection holder is null -- druid-1.0.9

        最近测试服务器过一晚上不用 , 第二天再来就会报connection holder is null  的异常 , 然后查询可以 , 对数据库的增删改操作就不能用了 .


        druid版本 1.0.9 , 这个问题 网上一搜一大堆 , 解决方案基本是要修改配置文件 .


       有一种说法是在执行较长的sql时 , 如果超过了 removeAbandonedTimeout  设置的时间 , 不管是否执行完 , 都会被释放掉 .


       但是我设置了一下 , 似乎没有用 .


      没有办法 , 只有看源码啦 .......... ╮(╯▽╰)╭


      错误日志是在这个地方打印的 ....


connection holder is null -- druid-1.0.9_第1张图片

       

        但是调用这个check方法的地方很多 , 初始化 , 获取连接 等地方都会先调这个方法 .


        不管怎么样 , 跟着代码看吧 , 先从初始化开始 ....


connection holder is null -- druid-1.0.9_第2张图片

    

       我的配置文件改成酱紫了 ..... 超时设置的是30分钟 ......................

  

connection holder is null -- druid-1.0.9_第3张图片


   但是初始化完了之后 , 从spring看 根本就木有这个属性 .... 


connection holder is null -- druid-1.0.9_第4张图片


   其他值倒是set进去了 ........


connection holder is null -- druid-1.0.9_第5张图片


看看初始化方法走完之后 , 有值了 .....但是 不是我们设的 .....


又找了找 ,  在 DruidAbstractDataSource 类中有给 removeAbandonedTimeoutMillis      属性设置默认值 


protected volatile long removeAbandonedTimeoutMillis              = 300 * 1000;


后面的判断也是按 removeAbandonedTimeoutMillis   来判断的 ;


是不是druid已经弃用这个removeAbandonedTimeout属性了 ?


要下班啦 , 阅兵放完假来接着跟这个问题 ......... 假期愉快


继续更~~


收回上面的推论 ,  由于本地项目是工程组组 , 在另一个引用到的工程里也有数据库配置 , 所以覆盖掉了测试配置 , 删除之后 , removeAbandoned相关属性是生效的 , 那么问题来了 .....


为什么属性设置是生效的 , 依然还是会报null异常呢 ?

public int removeAbandoned() {
    int removeCount = 0;
    long currrentNanos = System.nanoTime();
    ArrayList abandonedList = new ArrayList();
    Map i$ = this.activeConnections;
    synchronized(this.activeConnections) {
        Iterator pooledConnection = this.activeConnections.keySet().iterator();

        while(pooledConnection.hasNext()) {
            DruidPooledConnection buf = (DruidPooledConnection)pooledConnection.next();
            if(!buf.isRunning()) {
                long trace = (currrentNanos - buf.getConnectedTimeNano()) / 1000000L;
                if(trace >= this.removeAbandonedTimeoutMillis) {
                    pooledConnection.remove();
                    buf.setTraceEnable(false);
                    abandonedList.add(buf);
                }
            }
        }
    }

    if(abandonedList.size() > 0) {
        Iterator var12 = abandonedList.iterator();

        while(true) {
            DruidPooledConnection var13;
            do {
                if(!var12.hasNext()) {
                    return removeCount;
                }

                var13 = (DruidPooledConnection)var12.next();
                JdbcUtils.close(var13);
                var13.abandond();
                ++this.removeAbandonedCount;
                ++removeCount;
            } while(!this.isLogAbandoned());

            StringBuilder var14 = new StringBuilder();
            var14.append("abandon connection, open stackTrace\n");
            StackTraceElement[] var15 = var13.getConnectStackTrace();

            for(int i = 0; i < var15.length; ++i) {
                var14.append("\tat ");
                var14.append(var15[i].toString());
                var14.append("\n");
            }

            LOG.error(var14.toString());
        }
    } else {
        return removeCount;
    }
}

上面这段是网上说的造成 null 异常的代码 , 

this.activeConnections
的确会取使用中的链接 
如果超过 
currrentNanos - buf.getConnectedTimeNano()
这个条件
就会remove掉
 
  
在这里加个断点 , 慢慢跟 .
 
  
 
  
final void afterExecute() {
    DruidConnectionHolder holder = this.holder;
    if(holder != null && holder.getDataSource().isRemoveAbandoned()) {
        this.running = false;
        holder.setLastActiveTimeMillis(System.currentTimeMillis());
    }

}

在每次执行完之后 , 会执行上面这个方法 .
 
  
为了测试 , removeAbandonedTimeout 设置的是10秒 , 最大连接设置的是 5 个 , 过了几分钟 , 在调接口试试 , 连接池变成这样.....
 
  
 
  
 
  
哪里不对 , 对比一下之前的连接池 
 
  
 
  
 
明白上面问题了吧 , 下去改代码 , 晚上发一版看看明天还会不会有这问题 .
 
  


你可能感兴趣的:(数据库)