Java ConnectionPool连接不关闭,停留在睡觉
题
我有一个网络应用程序使用的JNDI查询获得的数据库连接。
连接收和返回查询,没有问题。这个问题我们连接不正确地关闭并被困在睡觉的方式(根据mysql管理员)。这意味着,他们变得无法使用nad然后我跑出来的连接。
有人能给我一些指针作为我可以做什么来使连接回到游泳池的成功。
public class DatabaseBean {
private static final Logger logger = Logger.getLogger(DatabaseBean.class);
private Connection conn;
private PreparedStatement prepStmt;
/**
* Zero argument constructor
* Setup generic databse connection in here to avoid redundancy
* The connection details are in /META-INF/context.xml
*/
public DatabaseBean() {
try {
InitialContext initContext = new InitialContext();
DataSource ds = (DataSource) initContext.lookup("java:/comp/env/jdbc/mysite");
conn = ds.getConnection();
}
catch (SQLException SQLEx) {
logger.fatal("There was a problem with the database connection.");
logger.fatal(SQLEx);
logger.fatal(SQLEx.getCause());
}
catch (NamingException nameEx) {
logger.fatal("There was a naming exception");
logger.fatal(nameEx);
logger.fatal(nameEx.getCause());
}
}
/**
* Execute a query. Do not use for statements (update delete insert etc).
*
* @return A ResultSet of the execute query. A set of size zero if no results were returned. It is never null.
* @see #executeUpdate() for running update, insert delete etc.
*/
public ResultSet executeQuery() {
ResultSet result = null;
try {
result = prepStmt.executeQuery();
logger.debug(prepStmt.toString());
}
catch (SQLException SQLEx) {
logger.fatal("There was an error running a query");
logger.fatal(SQLEx);
}
return result;
}
剪断
public void close() {
try {
prepStmt.close();
prepStmt = null;
conn.close();
conn = null;
} catch (SQLException SQLEx) {
logger.warn("There was an error closing the database connection.");
}
}
}
这是内javabean使用该数据库连接。
public LinkedList<ImportantNoticeBean> getImportantNotices() {
DatabaseBean noticesDBBean = new DatabaseBean();
LinkedList<ImportantNoticeBean> listOfNotices = new LinkedList<ImportantNoticeBean>();
try {
PreparedStatement preStmt = noticesDBBean.getConn().prepareStatement("SELECT pseudonym, message, date_to, date_from " +
"FROM importantnotices, users " +
"WHERE importantnotices.username = users.username " +
"AND NOW() >= date_from AND NOW() <= date_to;");
noticesDBBean.setPrepStmt(preStmt);
ResultSet result = noticesDBBean.executeQuery();
while (result.next()) {
ImportantNoticeBean noticeBean = new ImportantNoticeBean();
noticeBean.setAuthor(result.getString("pseudonym"));
noticeBean.setMessage(result.getString("message"));
noticeBean.setDateTo(result.getDate("date_to"));
noticeBean.setDateFrom(result.getDate("date_from"));
listOfNotices.add(noticeBean);
}
result.close();
} catch (SQLException SQLEx) {
logger.error("There was an error in ImportantNoticesBean.getImportantNotices()");
logger.error(SQLEx);
} finally {
noticesDBBean.close();
}
return listOfNotices;
}
<Context reloadable="true">
<Resource name="jdbc/mysite"
auth="Container"
type="javax.sql.DataSource"
username="user"
password="password"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mysite"
maxActive="10"
maxIdle="5"
maxWait="6000"
removeAbandoned="true"
logAbandoned="false"
removeAbandonedTimeout="20"
/>
</Context>
解决方案 4
这个问题我们连接不正确地关闭并被困在睡'模式
这实际上是只有一半的权利。
问题是我遇到的实际上是,每个应用程序是确定一个新的数据库连接切断。所以每次我闭所有连接应用程序将使一堆新的连接,作为每它的WEB.xml 配置文件和运行得很开心。应用程序,B会这样做。问题是他们 独立池 它试图抓住最多的服务器定义的限制。它是一种竞争条件,我猜。因此,当应用程序已经完成了连接,它坐落在等待以再次使用它们,直到超时已经过去,而应用程序B谁需要连接现在被拒绝的资源,尽管程序已经完成,并应能回到游泳池。一旦超时已经过去了,连接被释放和B(或等C)可以得到它了。
例如如果限制是10(mySQL轮廓限制),每个应用程序已经配置为使用最多的10所述,将有20次尝试连接。显然,这是一个糟糕的情况。
该方案是RTFM和把 连接的详细信息在正确的地方.这不会使共同发布的一个痛苦但是有办法绕过它(例如连接到其他xml文件从上下文)。
只是要明确:我把连接的细节WEB.xml 每个应用程序和有一个打击它。
其他提示
你似乎是关闭连接正确的除外情况下prepStmt.close()throws一SQLException,我不能找到一个连接泄漏。
什么池执行你们使用?当你接近一个连接,游泳池不需要靠近潜在的MySQL立即连接-毕竟这是指连接的一个游泳池!因此,从MySQL边,在连接就会看起来还活着,但你的程序是不使用任何;他们可能干脆将举行的TC连接池。
你可能想试验设置的连接池。要求它缩小的游泳池时系统被闲置。或者,要求它刷新所有连接的周期性。或者,有一个严格的上限数量的同时连接它曾经被从MySQL等。
一的方式检查,如果你的代码中有一个连接泄漏是迫使ds。块()始终打开一个新的物理连接和conn.close()释放的连接(如果你的连接池已设置的那些)。然后如果你看上的连接MySQL方面,你能够弄清楚,如果代码真的有一个连接泄漏或没有。
这是一个类似的问题- 连接池设置Tomcat
这是我的响应这个问题,它解决了这一问题的其他人。它可以帮助你。
可持续发展使用的雅加达共同数据库连接池。它依赖于数量的雅加达共同组成部分:
* Jakarta-Commons DBCP
* Jakarta-Commons Collections
* Jakarta-Commons Pool
我使用的是相同的连接集中的东西和我设置这些特性来防止同样的事情,它只是没有配置过tomcat。但是,如果第一件事不尝试。
testWhileIdle=true
timeBetweenEvictionRunsMillis=300000
好吧,我可能会有这样的排序。我已经改变了数据库的配置资源如下:
*SNIP*
maxActive="10"
maxIdle="5"
maxWait="7000"
removeAbandoned="true"
logAbandoned="false"
removeAbandonedTimeout="3"
*SNIP*
这工作不够好,现在。发生了什么,据我所知,是,一旦我到了十连接,然后Tomcat检查废弃的连接(空闲时间>3).它这样做是在批量工作,每次最大的连接。潜在的问题,这是如果我需要10多的查询,同时运行(不是唯一给我)。重要的是,removeAbandonedTimeout小于maxWait.
是这个应该是什么事?即是这种方式的游泳池应该运作?如果这是似乎是,至少对我来说,你会等待直到的东西(连接)被打破之前的固定,而不是不让它"中断"放在第一位。也许我仍然不能得到它。
一件事,@binil错过了,你是不是关闭的结果集中的情况的一个例外。根据驱动的实施,这可能导致连接保持开放。移动的结果。close()通话的最后块。
我用同样的配置。如果连接在mysql管理员(windows)表示,它是在睡觉的模式,它仅仅意味着汇集,但没有使用。我检查这个运行测试程序的程序与多线程的随机查询Mysql.如果它有助于在这里是我的配置:
defaultAutoCommit="false"
defaultTransactionIsolation="REPEATABLE_READ"
auth="Container"
type="javax.sql.DataSource"
logAbandoned="true"
removeAbandoned="true"
removeAbandonedTimeout="300"
maxActive="-1"
initialSize="15"
maxIdle="10"
maxWait="10000"
username="youruser"
password="youruserpassword"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://yourhost/yourdatabase"/>