BoneCP 的disableConnectionTracking配置

最近在项目中会偶然出现该信息:

BoneCP detected an unclosed connection and will now attempt to close it for you. You should be closing this connection in your application
 - enable connectionWatch for additional debugging assistance or set disableConnectionTracking to true to disable this feature entirely. 

随后就可能出现该异常:

Error while extracting database product name - falling back to empty error codes
org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
        at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:296)
        at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:320)
        at org.springframework.jdbc.support.SQLErrorCodesFactory.getErrorCodes(SQLErrorCodesFactory.java:214)
        at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.setDataSource(SQLErrorCodeSQLExceptionTranslator.java:141)


经过网上搜索后,发现有不少人也遇到了,他们的建议是在db链接上添加“autoreconect=true”,但是我发现,我们的链接已经包含该属性了。

然后继续,从百度转战到google。。。最后直接看了源码。。。 发现原来是bonecp在管理链接时,由ConnectionPartition中的trackConnectionFinalizer方法将链接都关闭回收掉了。

/** This method is a replacement for finalize() but avoids all its pitfalls (see Joshua Bloch et. all).
	 * 
	 * Keeps a handle on the connection. If the application called closed, then it means that the handle gets pushed back to the connection
	 * pool and thus we get a strong reference again. If the application forgot to call close() and subsequently lost the strong reference to it,
	 * the handle becomes eligible to garbage connection and thus the the finalizeReferent method kicks in to safely close off the database
	 * handle. Note that we do not return the connectionHandle back to the pool since that is not possible (for otherwise the GC would not 
	 * have kicked in), but we merely safely release the database internal handle and update our counters instead.
	 * @param connectionHandle handle to watch
	 */ 

以上是关于trackConnectionFinalizer方法的注解,大意为(翻译的很拙劣。。我自己都看不懂- -):

这个方法是finalize方法的另一种替代,它能避免finalize所有的陷阱。

设置一个ConnectionHandle在连接上。如果应用调用了closed方法,(then it means that the handle gets pushed back to the connection pool and thus we get a strong reference again)不会翻译这句- -。。 如果应用忘记调用了close方法,而后又失去了对连接的引用,先前设置的ConnectionHandle就能回收连接并安全的关闭它们。

注意:我们并没有将connectionHandle放回线程池,因为这是不可能的(否则,GC就无法生效),但是我们安全的释放了database内部的hanndle并且更新了计数器。


于是继续查看原因,原来是ConnectionPartition的addFreeConnection和MemorizeTransactionProxy的attemptRecovery的方法中调用到了该方法。。。继续看源码。。省略若干行。。


最后发现可能是在addFreeConnection时,调用了trackConnectionFinalizer方法导致的!从addFreeConnection方法中,找到了一个开关配置disableTracking:

// assume success to avoid racing where we insert an item in a queue and having that item immediately
		// taken and closed off thus decrementing the created connection count.
		updateCreatedConnections(1);
		if (!this.disableTracking){
			trackConnectionFinalizer(connectionHandle); 
		}
最后发现,这个是BoneCPConfig中的disableConnectionTracking属性,于是乎、、、、将配置文件中增加该配置信息:


		


由于不太会重现,所以现在还在观察中,应该是源头吧。。。

不是的话。。就呵呵了T_T。。


最后贴上BoneCPConfig中的 setDisableConnectionTracking的注解:

/** If set to true, the pool will not monitor connections for proper closure. Enable this option if you only ever obtain
	 * your connections via a mechanism that is guaranteed to release the connection back to the pool (eg Spring's jdbcTemplate, 
	 * some kind of transaction manager, etc).
	 * 
	 * @param disableConnectionTracking set to true to disable. Default: false.
	 */
	public void setDisableConnectionTracking(boolean disableConnectionTracking) {
		this.disableConnectionTracking = disableConnectionTracking;
	}
大意为: 如果设置为true,连接池将不会监控连接并进行适当的关闭。如果你只是通过一种机制获取你的连接,并且保证将连接释放到池中,就启用这个选项。(比如 Spring's jdbcTemplate,some kind of transaction manager 等)。


转载请标明: http://blog.csdn.net/fengyuxue11011/article/details/23760447 谢谢


你可能感兴趣的:(工作琐碎)