数据库连接池

发布时间 : 星期四 文章数据库连接池更新完毕开始阅读

wasCancelled = true;

} catch (SQLException sqlEx) {

throw new RuntimeException(sqlEx.toString()); } finally {

if (cancelStmt != null) { try {

cancelStmt.close();

} catch (SQLException sqlEx) {

throw new RuntimeException(sqlEx.toString()); } }

if (cancelConn != null) { try {

cancelConn.close();

} catch (SQLException sqlEx) {

throw new RuntimeException(sqlEx.toString()); } } } } };

cancelThread.start(); } }

class CancelTask extends TimerTask { long connectionId = 0;

CancelTask() throws SQLException {

connectionId = connection.getIO().getThreadId(); }

public void run() {

Thread cancelThread = new Thread() { public void run() {

Connection cancelConn = null;

java.sql.Statement cancelStmt = null; try {

cancelConn = connection.duplicate();

cancelStmt = cancelConn.createStatement();

// 简单暴力,再发起一条KILL SQL,关闭先前的sql thread id cancelStmt.execute(\wasCancelled = true;

} catch (SQLException sqlEx) {

throw new RuntimeException(sqlEx.toString()); } finally {

if (cancelStmt != null) { try {

cancelStmt.close();

} catch (SQLException sqlEx) {

throw new RuntimeException(sqlEx.toString()); } }

if (cancelConn != null) { try {

cancelConn.close();

} catch (SQLException sqlEx) {

throw new RuntimeException(sqlEx.toString()); } } } } };

cancelThread.start(); } }

原因总结一句话: queryTimeout的实现是通过底层数据库提供的机制,比如KILL QUERY pid. 如果此时的网络不通,出现阻塞现象,对应的kill命令也发不出去,所以timeout设置的超时没效果。 4.最后

最后还是决定配置testWhileIdle扫描,主要考虑:

pool池中的链接如果未被使用,可以通过testWhileIdle进行链接检查,避免在使用时后总要失败那么一次,可以及时预防

配合连接池的minEvictableIdleTimeMillis(空闲链接),removeAbandoned(未释放的链接),可以更好的去避免因为一些异常情况引起的问题,防范于未然。比如使用一些分布式数据库的中间件,会有空闲链接关闭的动作,动态伸缩连接池,这时候需要能及时的发现,避免请求失败。

testOnBorrow个人不太建议使用,存在性能问题,试想一下连接一般会在什么情况出问题,网络或者服务端异常终端空闲链接,网络中断你testOnBorrow检

查发现不对再取一个链接还是不对,针对空闲链接处理异常关闭,可以从好业务端的重试策略进行考虑,同时配置客户端的空闲链接超时时间,maxIdle,minIdle等。

-------------------------------------------- 新加的内容:

5.dbcp密码加密处理

以前使用jboss的jndi数据源的方式,是通过配置oracle-ds.xml,可以设置EncryptDBPassword,引用jboss login-config.xml配置的加密配置。

Java代码

code=\flag=\

name=\${jndiName}

< application-policy name=\

code=\flag=\

name=\${jndiName}

为了能达到同样的效果,切换为spring dbcp配置时,也有类似密码加密的功能,运行期进行密码decode,最后进行数据链接。

实现方式很简单,分析jboss的对应SecureIdentityLoginModule的实现,无非就是走了Blowfish加密算法,自己拷贝实现一份。

Java代码

private static String encode(String secret) throws NoSuchPaddingException, NoSuchAlgorithmException,

InvalidKeyException, BadPaddingException, IllegalBlockSizeException { byte[] kbytes = \

SecretKeySpec key = new SecretKeySpec(kbytes, \

Cipher cipher = Cipher.getInstance(\cipher.init(Cipher.ENCRYPT_MODE, key);

byte[] encoding = cipher.doFinal(secret.getBytes()); BigInteger n = new BigInteger(encoding); return n.toString(16); }

private static char[] decode(String secret) throws NoSuchPaddingException, NoSuchAlgorithmException,

InvalidKeyException, BadPaddingException, IllegalBlockSizeException { byte[] kbytes = \

SecretKeySpec key = new SecretKeySpec(kbytes, \

BigInteger n = new BigInteger(secret, 16); byte[] encoding = n.toByteArray();

Cipher cipher = Cipher.getInstance(\cipher.init(Cipher.DECRYPT_MODE, key); byte[] decode = cipher.doFinal(encoding); return new String(decode).toCharArray(); }

private static String encode(String secret) throws NoSuchPaddingException, NoSuchAlgorithmException,

InvalidKeyException, BadPaddingException, IllegalBlockSizeException { byte[] kbytes = \

SecretKeySpec key = new SecretKeySpec(kbytes, \Cipher cipher = Cipher.getInstance(\cipher.init(Cipher.ENCRYPT_MODE, key);

byte[] encoding = cipher.doFinal(secret.getBytes()); BigInteger n = new BigInteger(encoding);

联系合同范文客服:xxxxx#qq.com(#替换为@)