DBCP1.3数据库连接泄漏问题

DBCP1.3数据库连接泄漏问题

线上使用的dbcp版本1.3,数据库为达梦7。

问题

在生产环境下发现,dbcp所连接的库一旦因为其它原因挂掉,再次重启数据库后会话将直接撑爆数据库,接着导致数据库再次挂掉。

如图中所示,会话撑满100个(上限默认的为100),连接全部是IDLE。
DBCP1.3数据库连接泄漏问题_第1张图片

在参考issue DBCP-470后经本地测试发现问题重现。

问题主要原因是当所连接的数据库停机后,此时通过程序创建BasicDataSource对象来访问数据库时validateConnectionFactory方法抛异常导致datasource成员变量一直为空。

主要问题在于createDataSource()方法。

  1. 通过dataSource !=null来防止重复创建数据源
    DBCP1.3数据库连接泄漏问题_第2张图片

  2. 创建连接池

DBCP1.3数据库连接泄漏问题_第3张图片

问题在于createPoolableConnectionFactory方法里会调用validateConnectionFactory方法来校验目的库是否可连接。如果不可连接将抛出异常,这将导致createDataSourceInstance()不会走,也就不会实例化dataSource变量。

  1. 连接泄露
    上面由于在异常时没有实例化dataSource变量,当重复调用createDataSource()方法时,将导致createConnectionPool()方法会重复调用。

  2. GC无法回收
    createConnectionPool()方法中,调用GenericObjectPoolsetTimeBetweenEvictionRunsMillis()方法时会开启一个Timer。这将导致GenericObjectPool对象由于被Timer对象引用而一直无法被回收掉。

DBCP1.3数据库连接泄漏问题_第4张图片

DBCP1.3数据库连接泄漏问题_第5张图片

DBCP1.3数据库连接泄漏问题_第6张图片

  1. jmap生成dump文件分析
    线上数据库确实如图中所示有那么多连接数被占用。
    DBCP1.3数据库连接泄漏问题_第7张图片

解决问题

在dbcp-470问题中提到解决版本为1.4.1
DBCP1.3数据库连接泄漏问题_第8张图片

但是官网并没有release 1.4.1版本。
DBCP1.3数据库连接泄漏问题_第9张图片

随便通过在GIT上找到commons-dbcp源码,在其1.4版本的分支中发现问题已经解决。

DBCP1.3数据库连接泄漏问题_第10张图片

此处已经try-catch了,并有在finally块中关闭了上面创建的连接池。

此时下载该版本的源代码编译打包后,再经测试发现问题已经解决了。

编译后的jar包下载地址

你可能感兴趣的:(java)