连接池 驱动 oracle,Oracle JDBC驱动, Tomcat连接池的坑

之前开发过程中遇到脏数据的问题.经过一段时间的分析,结果如下:

1. 应用通过Tomcat JDBC Pool获得一个数据库连接;

2. 通过这个连接执行了一些Insert,Update之类;

3. 之后的业务代码,执行了一个时间比较长的查询;

4. Tomcat JDBC Pool 认为这个连接使用的时间过长,没有在配置的时间内(AbandonTimeout这个配置)把这个连接close,所以自动回收并Close了这个连接.

其实到这里都是没有问题的. 问题在于,这个连接被回收到连接池并Close之后,在1和2步骤中插入更新的数据没有回滚.

继续分析,发现如下的结果:

JDBC标准没有规定一个Connection Close的时候(这里说的close,是指程序正常调用close()方法,而不是说因为网络等等原因这个connection被中断了),如果没有Commit的表现. 所以很多人,包括我,理所当然认为,如果没有手动Comit或者Rollback,

JDBC Driver应该主动回滚. 但是因为标准没有规定,这个行为对于不同的驱动的实现是不一样的. 对于Oracle的驱动,在close的时候会替你commit.

所以这个问题就出现了:

连接池的检测线程发现某个连接池的连接,在配置的时间内没有归还给连接池,所以连接池主动close了这个连接. 但是对于Oracle,因为JDBC Driver会替你

commit,所以出现了尽管这个连接被关闭了,这个连接的更新还是被提交到了数据库中.

没有找到现成的配置;所以自己写了一个Tomcat JDBC Connection Pool Intepto来做这件事情:

public class RollbackInterptor extends JdbcInterceptor {

private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

@Override

public void reset(ConnectionPool parent,PooledConnection con) {

}

@Override

public void disconnected(ConnectionPool parent,PooledConnection con,boolean finalizing) {

logger.info("Disconnected called for {} {}",con,parent);

try {

if (con != null && con.getConnection() != null) {

con.getConnection().rollback();

logger.info("Connection {} has been rolled-back.",con);

}

} catch (Exception e) {

}

super.disconnected(parent,finalizing);

}

}

然后在配置连接池的地方加上就行了:

org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReport(threshold=5000);com.foo.bar.connection.RollbackInterptor

总结

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值