MyException - 我的异常网
当前位置:我的异常网» 数据库 » 数据库连接池跟事务

数据库连接池跟事务

www.MyException.Cn  网友分享于:2013-02-20  浏览:98次
数据库连接池和事务

背景

在高并发情况下,最近项目中出现了锁定量问题,可能原因是出库没有加上锁定量,入库没有减去锁定量,这样会导致不能正常的出库和入库。需要从几个方面来考虑

1、  业务过程中加锁存在问题

2、  事务没有正确提交

3、  提交了之前不合理的事务

4、  存在没有使用事务的业务

于是在数据库理论基础上,做了一些测试来推断问题所在。首先需要铺垫两方面内容:修改数据库my.ini文件,指定其连接最大等待时间。

默认设置如下:

需要修改wait_timeoutinteractive_timeout。在my.ini中,找到mysqld在其下增加

Wait_timeout=10

Interactive_timeout=10

修改数据库连接池,指定其回收连接最大等待时间。

removeAbandoned="true"

removeAbandonedTimeout="60"

logAbandoned="true"

这样只要两者不相等就可以分别模拟数据库连接关闭和连接池连接关闭情况下事务的执行情况。如下:

数据库连接关闭

用例1

插入test1,插入test2,插入test3,使数据库连接断开在插入test2处并捕获异常,

结论:

异常之后的所有操作都会报错,所有的操作都不能提交到数据库。错误信息如下:

1com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

 

The last packet successfullyreceived from the server was 37,281 milliseconds ago.  The last packet sent successfully to theserver was 0 milliseconds ago.

    atsun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

Caused by: java.net.SocketException: Software caused connection abort: recv failed

    atjava.net.SocketInputStream.socketRead0(Native Method)

2、构造preparedStatement

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.

    atsun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

3、执行

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after statement closed.

4、提交事务

java.sql.SQLException: Connection has already been closed.

    atorg.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:117)

    atorg.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99)

用例2

在用例1基础上,获取同一个连接,并提交事务

结论:

无法获取到同一个连接,当连接关闭后会销毁,下一次请求会创建新连接,因此用例1的未提交事务不会因为用例2的提交被重新提交

数据库连接池连接关闭

用例1

插入test1,插入test2,插入test3,使数据库连接池连接断开在插入test2处并捕获异常,

结论:

异常之后的所有操作都会报错,所有的操作都不能提交到数据库。错误信息如下:

1Connection has been abandoned PooledConnection[com.mysql.jdbc.JDBC4Connection@bc4a53]:java.lang.Exception

    atorg.apache.tomcat.jdbc.pool.ConnectionPool.getThreadDump(ConnectionPool.java:1023)

    atorg.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:689)

    atorg.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:616)

    atorg.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:179)

    atorg.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:126)

2、执行插入:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after statement closed.

    atsun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

    atsun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)

    atsun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)

    atjava.lang.reflect.Constructor.newInstance(Constructor.java:513)

3、提交事务

java.sql.SQLException: Connection has already been closed.

    atorg.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:117)

    atorg.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99)

    atorg.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor.invoke(AbstractCreateStatementInterceptor.java:71)

    atorg.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99)

    atorg.apache.tomcat.jdbc.pool.interceptor.ConnectionState.invoke(ConnectionState.java:140)

    atorg.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99)

    atorg.apache.tomcat.jdbc.pool.TrapException.invoke(TrapException.java:41)

    atorg.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99)

    atorg.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:58)

    at$Proxy4.getAutoCommit(Unknown Source)

    atadultadmin.util.db.DbOperation.commitTransaction(DbOperation.java:142)

用例2

在用例1基础上,获取同一个连接,并提交事务

结论:

无法获取到同一个连接,当连接关闭后连接池会丢弃这个连接,下一次请求会创建新连接,因此用例1的未提交事务不会因为用例2的提交而被重新提交

会造成数据异常原因

正常业务,没有显示进行手动回滚

第一次请求:插入test1,当插入test2时返回并且没有提交事务

第二次请求,获取到同一个连接,插入test1,test2,test3,查询数据库发现test1test2第一次请求的数据被插入

第三次请求,和第一次请求一致

第四次请求,获取不同连接,不会将第三次数据提交到数据库

正常业务,捕获异常后,没有返回

正常业务,没有判断意外,意外发生时没有显示进行手动回滚

没有使用事务

文章评论

软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有