【发布时间】:2014-10-08 17:48:14
【问题描述】:
我们的一个遗留应用程序中存在数据库连接泄漏,我将其追踪到这个小宝石。从调试中,我可以看到为多个线程返回了相同的逻辑连接(不好!)。但我很难理解为什么会这样。
我们正在使用 ojdbc6 驱动程序,在带有连接池的 WebLogic 数据源上设置。
产生问题的代码
public class MyDummyDaoUtil {
//note: this is a public field in a singleton (not a static field though...)
public Connection conn;
private MyDummyDaoUtil() {
}
public static MyDummyDaoUtil getInstance() {
if (instance == null) {
instance = new MyDummyDaoUtil();
}
return instance;
}
private DataSource getDataSource(final String dsName)
throws NamingException {
return ServiceLocator.getInstance().getDataSource(dsName);
}
public static Connection getConnection(final String source)
throws NamingException {
return MyDummyDaoUtil.getInstance().getDBConnection(source);
}
private Connection getDBConnection(final String source)
throws NamingException {
//the same logical connection is produced by the data source or something else happening?
conn = getDataSource(source).getConnection();
conn.setAutoCommit(false);
return conn;
}
}
更新修复
public class MyDummyDaoUtil {
private MyDummyDaoUtil() {
}
public static MyDummyDaoUtil getInstance() {
if (instance == null) {
instance = new MyDummyDaoUtil();
}
return instance;
}
private DataSource getDataSource(final String dsName)
throws NamingException {
return ServiceLocator.getInstance().getDataSource(dsName);
}
public static Connection getConnection(final String source)
throws NamingException {
return MyDummyDaoUtil.getInstance().getDBConnection(source);
}
private Connection getDBConnection(final String source)
throws NamingException {
Connection conn = getDataSource(source).getConnection();
conn.setAutoCommit(false);
return conn;
}
}
修复摘要
- 实例的延迟初始化不正确
- Connection 应该是方法中的局部变量,而不是单例类
【问题讨论】:
-
你说 MyDummyDaoUtil 是一个单例。如果这在多个线程之间共享,那么将有机会请求两个连接来改变引用,并且从两次调用 getDBConnection 返回相同的引用(最后一个)。未返回的连接永远无法关闭。这段代码最终不会耗尽可用的连接吗?
-
@Yoztastic 连接可能在垃圾回收时被终结器击落,从而隐藏了这个问题。
-
@Yoztastic - 是的,这是最初的症状。我们的连接已耗尽,我们不得不打开非活动超时来帮助回收那些泄露的连接,同时我们追踪问题。据我所知,代码从第一天开始就以这种方式实现(这很可怕......)目前还不清楚这个问题是如何在我们的旧系统上出现的。我的猜测是连接以某种方式被回收,我们没有意识到这个问题的存在。
标签: java multithreading jdbc database-connection connection-pooling